1 // Copyright (c) 2020 Google LLC
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 "source/fuzz/transformation_add_local_variable.h"
16
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "test/fuzz/fuzz_test_util.h"
20
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24
TEST(TransformationAddLocalVariableTest,BasicTest)25 TEST(TransformationAddLocalVariableTest, BasicTest) {
26 std::string shader = R"(
27 OpCapability Shader
28 %1 = OpExtInstImport "GLSL.std.450"
29 OpMemoryModel Logical GLSL450
30 OpEntryPoint Fragment %4 "main"
31 OpExecutionMode %4 OriginUpperLeft
32 OpSource ESSL 310
33 %2 = OpTypeVoid
34 %3 = OpTypeFunction %2
35 %6 = OpTypeInt 32 1
36 %7 = OpTypeStruct %6 %6
37 %8 = OpTypePointer Function %7
38 %10 = OpConstant %6 1
39 %11 = OpConstant %6 2
40 %12 = OpConstantComposite %7 %10 %11
41 %13 = OpTypeFloat 32
42 %14 = OpTypeInt 32 0
43 %15 = OpConstant %14 3
44 %16 = OpTypeArray %13 %15
45 %17 = OpTypeBool
46 %18 = OpTypeStruct %16 %7 %17
47 %19 = OpTypePointer Function %18
48 %21 = OpConstant %13 1
49 %22 = OpConstant %13 2
50 %23 = OpConstant %13 4
51 %24 = OpConstantComposite %16 %21 %22 %23
52 %25 = OpConstant %6 5
53 %26 = OpConstant %6 6
54 %27 = OpConstantComposite %7 %25 %26
55 %28 = OpConstantFalse %17
56 %29 = OpConstantComposite %18 %24 %27 %28
57 %30 = OpTypeVector %13 2
58 %31 = OpTypePointer Function %30
59 %33 = OpConstantComposite %30 %21 %21
60 %34 = OpTypeVector %17 3
61 %35 = OpTypePointer Function %34
62 %37 = OpConstantTrue %17
63 %38 = OpConstantComposite %34 %37 %28 %28
64 %39 = OpTypeVector %13 4
65 %40 = OpTypeMatrix %39 3
66 %41 = OpTypePointer Function %40
67 %43 = OpConstantComposite %39 %21 %22 %23 %21
68 %44 = OpConstantComposite %39 %22 %23 %21 %22
69 %45 = OpConstantComposite %39 %23 %21 %22 %23
70 %46 = OpConstantComposite %40 %43 %44 %45
71 %50 = OpTypePointer Function %14
72 %51 = OpConstantNull %14
73 %4 = OpFunction %2 None %3
74 %5 = OpLabel
75 OpReturn
76 OpFunctionEnd
77 )";
78
79 const auto env = SPV_ENV_UNIVERSAL_1_4;
80 const auto consumer = nullptr;
81 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
82 spvtools::ValidatorOptions validator_options;
83 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
84 kConsoleMessageConsumer));
85 TransformationContext transformation_context(
86 MakeUnique<FactManager>(context.get()), validator_options);
87 // A few cases of inapplicable transformations:
88 // Id 4 is already in use
89 ASSERT_FALSE(TransformationAddLocalVariable(4, 50, 4, 51, true)
90 .IsApplicable(context.get(), transformation_context));
91 // Type mismatch between initializer and pointer
92 ASSERT_FALSE(TransformationAddLocalVariable(105, 46, 4, 51, true)
93 .IsApplicable(context.get(), transformation_context));
94 // Id 5 is not a function
95 ASSERT_FALSE(TransformationAddLocalVariable(105, 50, 5, 51, true)
96 .IsApplicable(context.get(), transformation_context));
97
98 // %105 = OpVariable %50 Function %51
99 {
100 TransformationAddLocalVariable transformation(105, 50, 4, 51, true);
101 ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(105));
102 ASSERT_EQ(nullptr, context->get_instr_block(105));
103 ASSERT_TRUE(
104 transformation.IsApplicable(context.get(), transformation_context));
105 ApplyAndCheckFreshIds(transformation, context.get(),
106 &transformation_context);
107 ASSERT_EQ(spv::Op::OpVariable,
108 context->get_def_use_mgr()->GetDef(105)->opcode());
109 ASSERT_EQ(5, context->get_instr_block(105)->id());
110 }
111
112 // %104 = OpVariable %41 Function %46
113 {
114 TransformationAddLocalVariable transformation(104, 41, 4, 46, false);
115 ASSERT_TRUE(
116 transformation.IsApplicable(context.get(), transformation_context));
117 ApplyAndCheckFreshIds(transformation, context.get(),
118 &transformation_context);
119 }
120
121 // %103 = OpVariable %35 Function %38
122 {
123 TransformationAddLocalVariable transformation(103, 35, 4, 38, true);
124 ASSERT_TRUE(
125 transformation.IsApplicable(context.get(), transformation_context));
126 ApplyAndCheckFreshIds(transformation, context.get(),
127 &transformation_context);
128 }
129
130 // %102 = OpVariable %31 Function %33
131 {
132 TransformationAddLocalVariable transformation(102, 31, 4, 33, false);
133 ASSERT_TRUE(
134 transformation.IsApplicable(context.get(), transformation_context));
135 ApplyAndCheckFreshIds(transformation, context.get(),
136 &transformation_context);
137 }
138
139 // %101 = OpVariable %19 Function %29
140 {
141 TransformationAddLocalVariable transformation(101, 19, 4, 29, true);
142 ASSERT_TRUE(
143 transformation.IsApplicable(context.get(), transformation_context));
144 ApplyAndCheckFreshIds(transformation, context.get(),
145 &transformation_context);
146 }
147
148 // %100 = OpVariable %8 Function %12
149 {
150 TransformationAddLocalVariable transformation(100, 8, 4, 12, false);
151 ASSERT_TRUE(
152 transformation.IsApplicable(context.get(), transformation_context));
153 ApplyAndCheckFreshIds(transformation, context.get(),
154 &transformation_context);
155 }
156
157 ASSERT_FALSE(
158 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
159 ASSERT_TRUE(
160 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
161 ASSERT_FALSE(
162 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
163 ASSERT_TRUE(
164 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103));
165 ASSERT_FALSE(
166 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104));
167 ASSERT_TRUE(
168 transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105));
169
170 std::string after_transformation = R"(
171 OpCapability Shader
172 %1 = OpExtInstImport "GLSL.std.450"
173 OpMemoryModel Logical GLSL450
174 OpEntryPoint Fragment %4 "main"
175 OpExecutionMode %4 OriginUpperLeft
176 OpSource ESSL 310
177 %2 = OpTypeVoid
178 %3 = OpTypeFunction %2
179 %6 = OpTypeInt 32 1
180 %7 = OpTypeStruct %6 %6
181 %8 = OpTypePointer Function %7
182 %10 = OpConstant %6 1
183 %11 = OpConstant %6 2
184 %12 = OpConstantComposite %7 %10 %11
185 %13 = OpTypeFloat 32
186 %14 = OpTypeInt 32 0
187 %15 = OpConstant %14 3
188 %16 = OpTypeArray %13 %15
189 %17 = OpTypeBool
190 %18 = OpTypeStruct %16 %7 %17
191 %19 = OpTypePointer Function %18
192 %21 = OpConstant %13 1
193 %22 = OpConstant %13 2
194 %23 = OpConstant %13 4
195 %24 = OpConstantComposite %16 %21 %22 %23
196 %25 = OpConstant %6 5
197 %26 = OpConstant %6 6
198 %27 = OpConstantComposite %7 %25 %26
199 %28 = OpConstantFalse %17
200 %29 = OpConstantComposite %18 %24 %27 %28
201 %30 = OpTypeVector %13 2
202 %31 = OpTypePointer Function %30
203 %33 = OpConstantComposite %30 %21 %21
204 %34 = OpTypeVector %17 3
205 %35 = OpTypePointer Function %34
206 %37 = OpConstantTrue %17
207 %38 = OpConstantComposite %34 %37 %28 %28
208 %39 = OpTypeVector %13 4
209 %40 = OpTypeMatrix %39 3
210 %41 = OpTypePointer Function %40
211 %43 = OpConstantComposite %39 %21 %22 %23 %21
212 %44 = OpConstantComposite %39 %22 %23 %21 %22
213 %45 = OpConstantComposite %39 %23 %21 %22 %23
214 %46 = OpConstantComposite %40 %43 %44 %45
215 %50 = OpTypePointer Function %14
216 %51 = OpConstantNull %14
217 %4 = OpFunction %2 None %3
218 %5 = OpLabel
219 %100 = OpVariable %8 Function %12
220 %101 = OpVariable %19 Function %29
221 %102 = OpVariable %31 Function %33
222 %103 = OpVariable %35 Function %38
223 %104 = OpVariable %41 Function %46
224 %105 = OpVariable %50 Function %51
225 OpReturn
226 OpFunctionEnd
227 )";
228 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
229 }
230
231 } // namespace
232 } // namespace fuzz
233 } // namespace spvtools
234