diff options
Diffstat (limited to 'test/name_mapper_test.cpp')
-rw-r--r-- | test/name_mapper_test.cpp | 338 |
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 |