1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <algorithm>
16 #include <string>
17 #include <tuple>
18 #include <utility>
19 #include <vector>
20 
21 #include "test/opt/pass_fixture.h"
22 #include "test/opt/pass_utils.h"
23 
24 namespace spvtools {
25 namespace opt {
26 namespace {
27 
28 struct FreezeSpecConstantValueTypeTestCase {
29   const char* type_decl;
30   const char* spec_const;
31   const char* expected_frozen_const;
32 };
33 
34 using FreezeSpecConstantValueTypeTest =
35     PassTest<::testing::TestWithParam<FreezeSpecConstantValueTypeTestCase>>;
36 
TEST_P(FreezeSpecConstantValueTypeTest,PrimaryType)37 TEST_P(FreezeSpecConstantValueTypeTest, PrimaryType) {
38   auto& test_case = GetParam();
39   std::vector<const char*> text = {"OpCapability Shader",
40                                    "OpMemoryModel Logical GLSL450",
41                                    test_case.type_decl, test_case.spec_const};
42   std::vector<const char*> expected = {
43       "OpCapability Shader", "OpMemoryModel Logical GLSL450",
44       test_case.type_decl, test_case.expected_frozen_const};
45   SinglePassRunAndCheck<FreezeSpecConstantValuePass>(
46       JoinAllInsts(text), JoinAllInsts(expected), /* skip_nop = */ false);
47 }
48 
49 // Test each primary type.
50 INSTANTIATE_TEST_CASE_P(
51     PrimaryTypeSpecConst, FreezeSpecConstantValueTypeTest,
52     ::testing::ValuesIn(std::vector<FreezeSpecConstantValueTypeTestCase>({
53         // Type declaration, original spec constant definition, expected frozen
54         // spec constants.
55         {"%int = OpTypeInt 32 1", "%2 = OpSpecConstant %int 1",
56          "%int_1 = OpConstant %int 1"},
57         {"%uint = OpTypeInt 32 0", "%2 = OpSpecConstant %uint 1",
58          "%uint_1 = OpConstant %uint 1"},
59         {"%float = OpTypeFloat 32", "%2 = OpSpecConstant %float 3.1415",
60          "%float_3_1415 = OpConstant %float 3.1415"},
61         {"%double = OpTypeFloat 64", "%2 = OpSpecConstant %double 3.141592653",
62          "%double_3_141592653 = OpConstant %double 3.141592653"},
63         {"%bool = OpTypeBool", "%2 = OpSpecConstantTrue %bool",
64          "%true = OpConstantTrue %bool"},
65         {"%bool = OpTypeBool", "%2 = OpSpecConstantFalse %bool",
66          "%false = OpConstantFalse %bool"},
67     })));
68 
69 using FreezeSpecConstantValueRemoveDecorationTest = PassTest<::testing::Test>;
70 
TEST_F(FreezeSpecConstantValueRemoveDecorationTest,RemoveDecorationInstWithSpecId)71 TEST_F(FreezeSpecConstantValueRemoveDecorationTest,
72        RemoveDecorationInstWithSpecId) {
73   std::vector<const char*> text = {
74       // clang-format off
75                "OpCapability Shader",
76                "OpCapability Float64",
77           "%1 = OpExtInstImport \"GLSL.std.450\"",
78                "OpMemoryModel Logical GLSL450",
79                "OpEntryPoint Vertex %main \"main\"",
80                "OpSource GLSL 450",
81                "OpSourceExtension \"GL_GOOGLE_cpp_style_line_directive\"",
82                "OpSourceExtension \"GL_GOOGLE_include_directive\"",
83                "OpName %main \"main\"",
84                "OpDecorate %3 SpecId 200",
85                "OpDecorate %4 SpecId 201",
86                "OpDecorate %5 SpecId 202",
87                "OpDecorate %6 SpecId 203",
88        "%void = OpTypeVoid",
89           "%8 = OpTypeFunction %void",
90         "%int = OpTypeInt 32 1",
91           "%3 = OpSpecConstant %int 3",
92       "%float = OpTypeFloat 32",
93           "%4 = OpSpecConstant %float 3.1415",
94      "%double = OpTypeFloat 64",
95           "%5 = OpSpecConstant %double 3.14159265358979",
96        "%bool = OpTypeBool",
97           "%6 = OpSpecConstantTrue %bool",
98           "%13 = OpSpecConstantFalse %bool",
99        "%main = OpFunction %void None %8",
100          "%14 = OpLabel",
101                "OpReturn",
102                "OpFunctionEnd",
103       // clang-format on
104   };
105   std::string expected_disassembly = SelectiveJoin(text, [](const char* line) {
106     return std::string(line).find("SpecId") != std::string::npos;
107   });
108   std::vector<std::pair<const char*, const char*>> replacement_pairs = {
109       {"%3 = OpSpecConstant %int 3", "%int_3 = OpConstant %int 3"},
110       {"%4 = OpSpecConstant %float 3.1415",
111        "%float_3_1415 = OpConstant %float 3.1415"},
112       {"%5 = OpSpecConstant %double 3.14159265358979",
113        "%double_3_14159265358979 = OpConstant %double 3.14159265358979"},
114       {"%6 = OpSpecConstantTrue ", "%true = OpConstantTrue "},
115       {"%13 = OpSpecConstantFalse ", "%false = OpConstantFalse "},
116   };
117   for (auto& p : replacement_pairs) {
118     EXPECT_TRUE(FindAndReplace(&expected_disassembly, p.first, p.second))
119         << "text:\n"
120         << expected_disassembly << "\n"
121         << "find_str:\n"
122         << p.first << "\n"
123         << "replace_str:\n"
124         << p.second << "\n";
125   }
126   SinglePassRunAndCheck<FreezeSpecConstantValuePass>(JoinAllInsts(text),
127                                                      expected_disassembly,
128                                                      /* skip_nop = */ true);
129 }
130 
131 }  // namespace
132 }  // namespace opt
133 }  // namespace spvtools
134