aboutsummaryrefslogtreecommitdiff
path: root/test/name_mapper_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/name_mapper_test.cpp')
-rw-r--r--test/name_mapper_test.cpp338
1 files changed, 338 insertions, 0 deletions
diff --git a/test/name_mapper_test.cpp b/test/name_mapper_test.cpp
new file mode 100644
index 00000000..c201198e
--- /dev/null
+++ b/test/name_mapper_test.cpp
@@ -0,0 +1,338 @@
+// Copyright (c) 2016 Google 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.
+
+#include "gmock/gmock.h"
+
+#include "test_fixture.h"
+#include "unit_spirv.h"
+
+#include "source/name_mapper.h"
+
+using libspirv::NameMapper;
+using libspirv::FriendlyNameMapper;
+using spvtest::ScopedContext;
+using ::testing::Eq;
+
+namespace {
+
+TEST(TrivialNameTest, Samples) {
+ auto mapper = libspirv::GetTrivialNameMapper();
+ EXPECT_EQ(mapper(1), "1");
+ EXPECT_EQ(mapper(1999), "1999");
+ EXPECT_EQ(mapper(1024), "1024");
+}
+
+// A test case for the name mappers that actually look at an assembled module.
+struct NameIdCase {
+ std::string assembly; // Input assembly text
+ uint32_t id;
+ std::string expected_name;
+};
+
+using FriendlyNameTest =
+ spvtest::TextToBinaryTestBase<::testing::TestWithParam<NameIdCase>>;
+
+TEST_P(FriendlyNameTest, SingleMapping) {
+ ScopedContext context(SPV_ENV_UNIVERSAL_1_1);
+ auto words = CompileSuccessfully(GetParam().assembly, SPV_ENV_UNIVERSAL_1_1);
+ auto friendly_mapper =
+ FriendlyNameMapper(context.context, words.data(), words.size());
+ NameMapper mapper = friendly_mapper.GetNameMapper();
+ EXPECT_THAT(mapper(GetParam().id), Eq(GetParam().expected_name))
+ << GetParam().assembly << std::endl
+ << " for id " << GetParam().id;
+}
+
+INSTANTIATE_TEST_CASE_P(ScalarType, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeVoid", 1, "void"},
+ {"%1 = OpTypeBool", 1, "bool"},
+ {"%1 = OpTypeInt 8 0", 1, "uchar"},
+ {"%1 = OpTypeInt 8 1", 1, "char"},
+ {"%1 = OpTypeInt 16 0", 1, "ushort"},
+ {"%1 = OpTypeInt 16 1", 1, "short"},
+ {"%1 = OpTypeInt 32 0", 1, "uint"},
+ {"%1 = OpTypeInt 32 1", 1, "int"},
+ {"%1 = OpTypeInt 64 0", 1, "ulong"},
+ {"%1 = OpTypeInt 64 1", 1, "long"},
+ {"%1 = OpTypeInt 1 0", 1, "u1"},
+ {"%1 = OpTypeInt 1 1", 1, "i1"},
+ {"%1 = OpTypeInt 33 0", 1, "u33"},
+ {"%1 = OpTypeInt 33 1", 1, "i33"},
+
+ {"%1 = OpTypeFloat 16", 1, "half"},
+ {"%1 = OpTypeFloat 32", 1, "float"},
+ {"%1 = OpTypeFloat 64", 1, "double"},
+ {"%1 = OpTypeFloat 10", 1, "fp10"},
+ {"%1 = OpTypeFloat 55", 1, "fp55"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ VectorType, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeBool %2 = OpTypeVector %1 1", 2, "v1bool"},
+ {"%1 = OpTypeBool %2 = OpTypeVector %1 2", 2, "v2bool"},
+ {"%1 = OpTypeBool %2 = OpTypeVector %1 3", 2, "v3bool"},
+ {"%1 = OpTypeBool %2 = OpTypeVector %1 4", 2, "v4bool"},
+
+ {"%1 = OpTypeInt 8 0 %2 = OpTypeVector %1 2", 2, "v2uchar"},
+ {"%1 = OpTypeInt 16 1 %2 = OpTypeVector %1 3", 2, "v3short"},
+ {"%1 = OpTypeInt 32 0 %2 = OpTypeVector %1 4", 2, "v4uint"},
+ {"%1 = OpTypeInt 64 1 %2 = OpTypeVector %1 3", 2, "v3long"},
+ {"%1 = OpTypeInt 20 0 %2 = OpTypeVector %1 4", 2, "v4u20"},
+ {"%1 = OpTypeInt 21 1 %2 = OpTypeVector %1 3", 2, "v3i21"},
+
+ {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2", 2, "v2float"},
+ // OpName overrides the element name.
+ {"OpName %1 \"time\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2", 2,
+ "v2time"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ MatrixType, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeBool %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 2", 3,
+ "mat2v2bool"},
+ {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 3", 3,
+ "mat3v2float"},
+ {"%1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = OpTypeMatrix %2 4", 3,
+ "mat4v2float"},
+ {"OpName %1 \"time\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 = "
+ "OpTypeMatrix %2 4",
+ 3, "mat4v2time"},
+ {"OpName %2 \"lat_long\" %1 = OpTypeFloat 32 %2 = OpTypeVector %1 2 %3 "
+ "= OpTypeMatrix %2 4",
+ 3, "mat4lat_long"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ OpName, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"OpName %1 \"abcdefg\"", 1, "abcdefg"},
+ {"OpName %1 \"Hello world!\"", 1, "Hello_world_"},
+ {"OpName %1 \"0123456789\"", 1, "0123456789"},
+ {"OpName %1 \"_\"", 1, "_"},
+ // An empty string is not valid for SPIR-V assembly IDs.
+ {"OpName %1 \"\"", 1, "_"},
+ // Test uniqueness when presented with things mapping to "_"
+ {"OpName %1 \"\" OpName %2 \"\"", 1, "_"},
+ {"OpName %1 \"\" OpName %2 \"\"", 2, "__0"},
+ {"OpName %1 \"\" OpName %2 \"\" OpName %3 \"_\"", 3, "__1"},
+ // Test uniqueness of names that are forced to be
+ // numbers.
+ {"OpName %1 \"2\" OpName %2 \"2\"", 1, "2"},
+ {"OpName %1 \"2\" OpName %2 \"2\"", 2, "2_0"},
+ // Test uniqueness in the face of forward references
+ // for Ids that don't already have friendly names.
+ // In particular, the first OpDecorate assigns the name, and
+ // the second one can't override it.
+ {"OpDecorate %1 Volatile OpDecorate %1 Restrict", 1, "1"},
+ // But a forced name can override the name that
+ // would have been assigned via the OpDecorate
+ // forward reference.
+ {"OpName %1 \"mememe\" OpDecorate %1 Volatile OpDecorate %1 Restrict",
+ 1, "mememe"},
+ // OpName can override other inferences. We assume valid instruction
+ // ordering, where OpName precedes type definitions.
+ {"OpName %1 \"myfloat\" %1 = OpTypeFloat 32", 1, "myfloat"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ UniquenessHeuristic, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 1, "void"},
+ {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 2, "void_0"},
+ {"%1 = OpTypeVoid %2 = OpTypeVoid %3 = OpTypeVoid", 3, "void_1"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(Arrays, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"OpName %2 \"FortyTwo\" %1 = OpTypeFloat 32 "
+ "%2 = OpConstant %1 42 %3 = OpTypeArray %1 %2",
+ 3, "_arr_float_FortyTwo"},
+ {"%1 = OpTypeInt 32 0 "
+ "%2 = OpTypeRuntimeArray %1",
+ 2, "_runtimearr_uint"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(Structs, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeBool "
+ "%2 = OpTypeStruct %1 %1 %1",
+ 2, "_struct_2"},
+ {"%1 = OpTypeBool "
+ "%2 = OpTypeStruct %1 %1 %1 "
+ "%3 = OpTypeStruct %2 %2",
+ 3, "_struct_3"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ Pointer, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeFloat 32 %2 = OpTypePointer Workgroup %1", 2,
+ "_ptr_Workgroup_float"},
+ {"%1 = OpTypeBool %2 = OpTypePointer Private %1", 2,
+ "_ptr_Private_bool"},
+ // OpTypeForwardPointer doesn't force generation of the name for its
+ // target type.
+ {"%1 = OpTypeBool OpTypeForwardPointer %2 Private %2 = OpTypePointer "
+ "Private %1",
+ 2, "_ptr_Private_bool"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(ExoticTypes, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeEvent", 1, "Event"},
+ {"%1 = OpTypeDeviceEvent", 1, "DeviceEvent"},
+ {"%1 = OpTypeReserveId", 1, "ReserveId"},
+ {"%1 = OpTypeQueue", 1, "Queue"},
+ {"%1 = OpTypeOpaque \"hello world!\"", 1, "Opaque_hello_world_"},
+ {"%1 = OpTypePipe ReadOnly", 1, "PipeReadOnly"},
+ {"%1 = OpTypePipe WriteOnly", 1, "PipeWriteOnly"},
+ {"%1 = OpTypePipe ReadWrite", 1, "PipeReadWrite"},
+ {"%1 = OpTypePipeStorage", 1, "PipeStorage"},
+ {"%1 = OpTypeNamedBarrier", 1, "NamedBarrier"},
+ }), );
+
+// Makes a test case for a BuiltIn variable declaration.
+NameIdCase BuiltInCase(std::string assembly_name, std::string expected) {
+ return NameIdCase{std::string("OpDecorate %1 BuiltIn ") + assembly_name +
+ " %1 = OpVariable %2 Input",
+ 1, expected};
+}
+
+// Makes a test case for a BuiltIn variable declaration. In this overload,
+// the expected result is the same as the assembly name.
+NameIdCase BuiltInCase(std::string assembly_name) {
+ return BuiltInCase(assembly_name, assembly_name);
+}
+
+// Makes a test case for a BuiltIn variable declaration. In this overload,
+// the expected result is the same as the assembly name, but with a "gl_"
+// prefix.
+NameIdCase BuiltInGLCase(std::string assembly_name) {
+ return BuiltInCase(assembly_name, std::string("gl_") + assembly_name);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ BuiltIns, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ BuiltInGLCase("Position"),
+ BuiltInGLCase("PointSize"),
+ BuiltInGLCase("ClipDistance"),
+ BuiltInGLCase("CullDistance"),
+ BuiltInCase("VertexId", "gl_VertexID"),
+ BuiltInCase("InstanceId", "gl_InstanceID"),
+ BuiltInCase("PrimitiveId", "gl_PrimitiveID"),
+ BuiltInCase("InvocationId", "gl_InvocationID"),
+ BuiltInGLCase("Layer"),
+ BuiltInGLCase("ViewportIndex"),
+ BuiltInGLCase("TessLevelOuter"),
+ BuiltInGLCase("TessLevelInner"),
+ BuiltInGLCase("TessCoord"),
+ BuiltInGLCase("PatchVertices"),
+ BuiltInGLCase("FragCoord"),
+ BuiltInGLCase("PointCoord"),
+ BuiltInGLCase("FrontFacing"),
+ BuiltInCase("SampleId", "gl_SampleID"),
+ BuiltInGLCase("SamplePosition"),
+ BuiltInGLCase("SampleMask"),
+ BuiltInGLCase("FragDepth"),
+ BuiltInGLCase("HelperInvocation"),
+ BuiltInCase("NumWorkgroups", "gl_NumWorkGroups"),
+ BuiltInCase("WorkgroupSize", "gl_WorkGroupSize"),
+ BuiltInCase("WorkgroupId", "gl_WorkGroupID"),
+ BuiltInCase("LocalInvocationId", "gl_LocalInvocationID"),
+ BuiltInCase("GlobalInvocationId", "gl_GlobalInvocationID"),
+ BuiltInGLCase("LocalInvocationIndex"),
+ BuiltInCase("WorkDim"),
+ BuiltInCase("GlobalSize"),
+ BuiltInCase("EnqueuedWorkgroupSize"),
+ BuiltInCase("GlobalOffset"),
+ BuiltInCase("GlobalLinearId"),
+ BuiltInCase("SubgroupSize"),
+ BuiltInCase("SubgroupMaxSize"),
+ BuiltInCase("NumSubgroups"),
+ BuiltInCase("NumEnqueuedSubgroups"),
+ BuiltInCase("SubgroupId"),
+ BuiltInCase("SubgroupLocalInvocationId"),
+ BuiltInGLCase("VertexIndex"),
+ BuiltInGLCase("InstanceIndex"),
+ BuiltInCase("SubgroupEqMaskKHR"),
+ BuiltInCase("SubgroupGeMaskKHR"),
+ BuiltInCase("SubgroupGtMaskKHR"),
+ BuiltInCase("SubgroupLeMaskKHR"),
+ BuiltInCase("SubgroupLtMaskKHR"),
+ }), );
+
+INSTANTIATE_TEST_CASE_P(DebugNameOverridesBuiltin, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"OpName %1 \"foo\" OpDecorate %1 BuiltIn WorkDim "
+ "%1 = OpVariable %2 Input",
+ 1, "foo"}}), );
+
+INSTANTIATE_TEST_CASE_P(
+ SimpleIntegralConstants, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 0", 2, "uint_0"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 1", 2, "uint_1"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 2", 2, "uint_2"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 9", 2, "uint_9"},
+ {"%1 = OpTypeInt 32 0 %2 = OpConstant %1 42", 2, "uint_42"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 0", 2, "int_0"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 1", 2, "int_1"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 2", 2, "int_2"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 9", 2, "int_9"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 42", 2, "int_42"},
+ {"%1 = OpTypeInt 32 1 %2 = OpConstant %1 -42", 2, "int_n42"},
+ // Exotic bit widths
+ {"%1 = OpTypeInt 33 0 %2 = OpConstant %1 0", 2, "u33_0"},
+ {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 10", 2, "i33_10"},
+ {"%1 = OpTypeInt 33 1 %2 = OpConstant %1 -19", 2, "i33_n19"},
+ }), );
+
+INSTANTIATE_TEST_CASE_P(
+ SimpleFloatConstants, FriendlyNameTest,
+ ::testing::ValuesIn(std::vector<NameIdCase>{
+ {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ff4p+16", 2,
+ "half_0x1_ff4p_16"},
+ {"%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.d2cp-10", 2,
+ "half_n0x1_d2cpn10"},
+ // 32-bit floats
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -3.275", 2, "float_n3_275"},
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128", 2,
+ "float_0x1_8p_128"}, // NaN
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128", 2,
+ "float_n0x1_0002p_128"}, // NaN
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128", 2,
+ "float_0x1p_128"}, // Inf
+ {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128", 2,
+ "float_n0x1p_128"}, // -Inf
+ // 64-bit floats
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -3.275", 2, "double_n3_275"},
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.ffffffffffffap-1023", 2,
+ "double_0x1_ffffffffffffapn1023"}, // small normal
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.ffffffffffffap-1023", 2,
+ "double_n0x1_ffffffffffffapn1023"},
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024", 2,
+ "double_0x1_8p_1024"}, // NaN
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0002p+1024", 2,
+ "double_n0x1_0002p_1024"}, // NaN
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024", 2,
+ "double_0x1p_1024"}, // Inf
+ {"%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024", 2,
+ "double_n0x1p_1024"}, // -Inf
+ }), );
+
+} // anonymous namespace