1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef TEST_UNIT_SPIRV_H_
#define TEST_UNIT_SPIRV_H_
#include <stdint.h>
#include <iomanip>
#include <string>
#include <vector>
#include "gtest/gtest.h"
#include "source/assembly_grammar.h"
#include "source/binary.h"
#include "source/diagnostic.h"
#include "source/enum_set.h"
#include "source/opcode.h"
#include "source/spirv_endian.h"
#include "source/text.h"
#include "source/text_handler.h"
#include "source/val/validate.h"
#include "spirv-tools/libspirv.h"
#ifdef __ANDROID__
#include <sstream>
namespace std {
template <typename T>
std::string to_string(const T& val) {
std::ostringstream os;
os << val;
return os.str();
}
} // namespace std
#endif
// Determine endianness & predicate tests on it
enum {
I32_ENDIAN_LITTLE = 0x03020100ul,
I32_ENDIAN_BIG = 0x00010203ul,
};
static const union {
unsigned char bytes[4];
uint32_t value;
} o32_host_order = {{0, 1, 2, 3}};
#define I32_ENDIAN_HOST (o32_host_order.value)
// A namespace for utilities used in SPIR-V Tools unit tests.
namespace spvtest {
class WordVector;
// Emits the given word vector to the given stream.
// This function can be used by the gtest value printer.
void PrintTo(const WordVector& words, ::std::ostream* os);
// A proxy class to allow us to easily write out vectors of SPIR-V words.
class WordVector {
public:
explicit WordVector(const std::vector<uint32_t>& val) : value_(val) {}
explicit WordVector(const spv_binary_t& binary)
: value_(binary.code, binary.code + binary.wordCount) {}
// Returns the underlying vector.
const std::vector<uint32_t>& value() const { return value_; }
// Returns the string representation of this word vector.
std::string str() const {
std::ostringstream os;
PrintTo(*this, &os);
return os.str();
}
private:
const std::vector<uint32_t> value_;
};
inline void PrintTo(const WordVector& words, ::std::ostream* os) {
size_t count = 0;
const auto saved_flags = os->flags();
const auto saved_fill = os->fill();
for (uint32_t value : words.value()) {
*os << "0x" << std::setw(8) << std::setfill('0') << std::hex << value
<< " ";
if (count++ % 8 == 7) {
*os << std::endl;
}
}
os->flags(saved_flags);
os->fill(saved_fill);
}
// Returns a vector of words representing a single instruction with the
// given opcode and operand words as a vector.
inline std::vector<uint32_t> MakeInstruction(
spv::Op opcode, const std::vector<uint32_t>& args) {
std::vector<uint32_t> result{
spvOpcodeMake(uint16_t(args.size() + 1), opcode)};
result.insert(result.end(), args.begin(), args.end());
return result;
}
// Returns a vector of words representing a single instruction with the
// given opcode and whose operands are the concatenation of the two given
// argument lists.
inline std::vector<uint32_t> MakeInstruction(
spv::Op opcode, std::vector<uint32_t> args,
const std::vector<uint32_t>& extra_args) {
args.insert(args.end(), extra_args.begin(), extra_args.end());
return MakeInstruction(opcode, args);
}
// Returns the vector of words representing the concatenation
// of all input vectors.
inline std::vector<uint32_t> Concatenate(
const std::vector<std::vector<uint32_t>>& instructions) {
std::vector<uint32_t> result;
for (const auto& instruction : instructions) {
result.insert(result.end(), instruction.begin(), instruction.end());
}
return result;
}
// A type for easily creating spv_text_t values, with an implicit conversion to
// spv_text.
struct AutoText {
explicit AutoText(const std::string& value)
: str(value), text({str.data(), str.size()}) {}
operator spv_text() { return &text; }
std::string str;
spv_text_t text;
};
// An example case for an enumerated value, optionally with operands.
template <typename E>
class EnumCase {
public:
EnumCase() = default; // Required by ::testing::Combine().
EnumCase(E val, std::string enum_name, std::vector<uint32_t> ops = {})
: enum_value_(val), name_(enum_name), operands_(ops) {}
// Returns the enum value as a uint32_t.
uint32_t value() const { return static_cast<uint32_t>(enum_value_); }
// Returns the name of the enumerant.
const std::string& name() const { return name_; }
// Returns a reference to the operands.
const std::vector<uint32_t>& operands() const { return operands_; }
private:
E enum_value_;
std::string name_;
std::vector<uint32_t> operands_;
};
// Returns a string with num_4_byte_chars Unicode characters,
// each of which has a 4-byte UTF-8 encoding.
inline std::string MakeLongUTF8String(size_t num_4_byte_chars) {
// An example of a longest valid UTF-8 character.
// Be explicit about the character type because Microsoft compilers can
// otherwise interpret the character string as being over wide (16-bit)
// characters. Ideally, we would just use a C++11 UTF-8 string literal,
// but we want to support older Microsoft compilers.
const std::basic_string<char> earth_africa("\xF0\x9F\x8C\x8D");
EXPECT_EQ(4u, earth_africa.size());
std::string result;
result.reserve(num_4_byte_chars * 4);
for (size_t i = 0; i < num_4_byte_chars; i++) {
result += earth_africa;
}
EXPECT_EQ(4 * num_4_byte_chars, result.size());
return result;
}
// Returns a vector of all valid target environment enums.
inline std::vector<spv_target_env> AllTargetEnvironments() {
return {
SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_1_2,
SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0,
SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1,
SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2,
SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,
SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2,
SPV_ENV_OPENGL_4_3, SPV_ENV_OPENGL_4_5,
SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3,
SPV_ENV_VULKAN_1_1,
};
}
// Returns the capabilities in a CapabilitySet as an ordered vector.
inline std::vector<spv::Capability> ElementsIn(
const spvtools::CapabilitySet& capabilities) {
return std::vector<spv::Capability>(capabilities.cbegin(),
capabilities.cend());
}
} // namespace spvtest
#endif // TEST_UNIT_SPIRV_H_
|