1 // Copyright (c) 2019 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_set_function_control.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(TransformationSetFunctionControlTest,VariousScenarios)25 TEST(TransformationSetFunctionControlTest, VariousScenarios) {
26 // This is a simple transformation; this test captures the important things
27 // to check for.
28
29 std::string shader = R"(
30 OpCapability Shader
31 %1 = OpExtInstImport "GLSL.std.450"
32 OpMemoryModel Logical GLSL450
33 OpEntryPoint Fragment %4 "main" %54
34 OpExecutionMode %4 OriginUpperLeft
35 OpSource ESSL 310
36 OpName %4 "main"
37 OpName %11 "foo(i1;i1;"
38 OpName %9 "a"
39 OpName %10 "b"
40 OpName %13 "bar("
41 OpName %17 "baz(i1;"
42 OpName %16 "x"
43 OpName %21 "boo(i1;i1;"
44 OpName %19 "a"
45 OpName %20 "b"
46 OpName %29 "g"
47 OpName %42 "param"
48 OpName %44 "param"
49 OpName %45 "param"
50 OpName %48 "param"
51 OpName %49 "param"
52 OpName %54 "color"
53 OpDecorate %54 Location 0
54 %2 = OpTypeVoid
55 %3 = OpTypeFunction %2
56 %6 = OpTypeInt 32 1
57 %7 = OpTypePointer Function %6
58 %8 = OpTypeFunction %6 %7 %7
59 %15 = OpTypeFunction %6 %7
60 %28 = OpTypePointer Private %6
61 %29 = OpVariable %28 Private
62 %30 = OpConstant %6 2
63 %31 = OpConstant %6 5
64 %51 = OpTypeFloat 32
65 %52 = OpTypeVector %51 4
66 %53 = OpTypePointer Output %52
67 %54 = OpVariable %53 Output
68 %4 = OpFunction %2 None %3
69 %5 = OpLabel
70 %42 = OpVariable %7 Function
71 %44 = OpVariable %7 Function
72 %45 = OpVariable %7 Function
73 %48 = OpVariable %7 Function
74 %49 = OpVariable %7 Function
75 %41 = OpFunctionCall %2 %13
76 OpStore %42 %30
77 %43 = OpFunctionCall %6 %17 %42
78 OpStore %44 %31
79 %46 = OpLoad %6 %29
80 OpStore %45 %46
81 %47 = OpFunctionCall %6 %21 %44 %45
82 OpStore %48 %43
83 OpStore %49 %47
84 %50 = OpFunctionCall %6 %11 %48 %49
85 OpReturn
86 OpFunctionEnd
87 %11 = OpFunction %6 Const %8
88 %9 = OpFunctionParameter %7
89 %10 = OpFunctionParameter %7
90 %12 = OpLabel
91 %23 = OpLoad %6 %9
92 %24 = OpLoad %6 %10
93 %25 = OpIAdd %6 %23 %24
94 OpReturnValue %25
95 OpFunctionEnd
96 %13 = OpFunction %2 Inline %3
97 %14 = OpLabel
98 OpStore %29 %30
99 OpReturn
100 OpFunctionEnd
101 %17 = OpFunction %6 Pure|DontInline %15
102 %16 = OpFunctionParameter %7
103 %18 = OpLabel
104 %32 = OpLoad %6 %16
105 %33 = OpIAdd %6 %31 %32
106 OpReturnValue %33
107 OpFunctionEnd
108 %21 = OpFunction %6 DontInline %8
109 %19 = OpFunctionParameter %7
110 %20 = OpFunctionParameter %7
111 %22 = OpLabel
112 %36 = OpLoad %6 %19
113 %37 = OpLoad %6 %20
114 %38 = OpIMul %6 %36 %37
115 OpReturnValue %38
116 OpFunctionEnd
117 )";
118
119 const auto env = SPV_ENV_UNIVERSAL_1_3;
120 const auto consumer = nullptr;
121 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
122
123 spvtools::ValidatorOptions validator_options;
124 TransformationContext transformation_context(
125 MakeUnique<FactManager>(context.get()), validator_options);
126 // %36 is not a function
127 ASSERT_FALSE(TransformationSetFunctionControl(36, SpvFunctionControlMaskNone)
128 .IsApplicable(context.get(), transformation_context));
129 // Cannot add the Pure function control to %4 as it did not already have it
130 ASSERT_FALSE(TransformationSetFunctionControl(4, SpvFunctionControlPureMask)
131 .IsApplicable(context.get(), transformation_context));
132 // Cannot add the Const function control to %21 as it did not already
133 // have it
134 ASSERT_FALSE(TransformationSetFunctionControl(21, SpvFunctionControlConstMask)
135 .IsApplicable(context.get(), transformation_context));
136
137 // Set to None, removing Const
138 TransformationSetFunctionControl transformation1(11,
139 SpvFunctionControlMaskNone);
140 ASSERT_TRUE(
141 transformation1.IsApplicable(context.get(), transformation_context));
142 ApplyAndCheckFreshIds(transformation1, context.get(),
143 &transformation_context);
144
145 // Set to Inline; silly to do it on an entry point, but it is allowed
146 TransformationSetFunctionControl transformation2(
147 4, SpvFunctionControlInlineMask);
148 ASSERT_TRUE(
149 transformation2.IsApplicable(context.get(), transformation_context));
150 ApplyAndCheckFreshIds(transformation2, context.get(),
151 &transformation_context);
152
153 // Set to Pure, removing DontInline
154 TransformationSetFunctionControl transformation3(17,
155 SpvFunctionControlPureMask);
156 ASSERT_TRUE(
157 transformation3.IsApplicable(context.get(), transformation_context));
158 ApplyAndCheckFreshIds(transformation3, context.get(),
159 &transformation_context);
160
161 // Change from Inline to DontInline
162 TransformationSetFunctionControl transformation4(
163 13, SpvFunctionControlDontInlineMask);
164 ASSERT_TRUE(
165 transformation4.IsApplicable(context.get(), transformation_context));
166 ApplyAndCheckFreshIds(transformation4, context.get(),
167 &transformation_context);
168
169 std::string after_transformation = R"(
170 OpCapability Shader
171 %1 = OpExtInstImport "GLSL.std.450"
172 OpMemoryModel Logical GLSL450
173 OpEntryPoint Fragment %4 "main" %54
174 OpExecutionMode %4 OriginUpperLeft
175 OpSource ESSL 310
176 OpName %4 "main"
177 OpName %11 "foo(i1;i1;"
178 OpName %9 "a"
179 OpName %10 "b"
180 OpName %13 "bar("
181 OpName %17 "baz(i1;"
182 OpName %16 "x"
183 OpName %21 "boo(i1;i1;"
184 OpName %19 "a"
185 OpName %20 "b"
186 OpName %29 "g"
187 OpName %42 "param"
188 OpName %44 "param"
189 OpName %45 "param"
190 OpName %48 "param"
191 OpName %49 "param"
192 OpName %54 "color"
193 OpDecorate %54 Location 0
194 %2 = OpTypeVoid
195 %3 = OpTypeFunction %2
196 %6 = OpTypeInt 32 1
197 %7 = OpTypePointer Function %6
198 %8 = OpTypeFunction %6 %7 %7
199 %15 = OpTypeFunction %6 %7
200 %28 = OpTypePointer Private %6
201 %29 = OpVariable %28 Private
202 %30 = OpConstant %6 2
203 %31 = OpConstant %6 5
204 %51 = OpTypeFloat 32
205 %52 = OpTypeVector %51 4
206 %53 = OpTypePointer Output %52
207 %54 = OpVariable %53 Output
208 %4 = OpFunction %2 Inline %3
209 %5 = OpLabel
210 %42 = OpVariable %7 Function
211 %44 = OpVariable %7 Function
212 %45 = OpVariable %7 Function
213 %48 = OpVariable %7 Function
214 %49 = OpVariable %7 Function
215 %41 = OpFunctionCall %2 %13
216 OpStore %42 %30
217 %43 = OpFunctionCall %6 %17 %42
218 OpStore %44 %31
219 %46 = OpLoad %6 %29
220 OpStore %45 %46
221 %47 = OpFunctionCall %6 %21 %44 %45
222 OpStore %48 %43
223 OpStore %49 %47
224 %50 = OpFunctionCall %6 %11 %48 %49
225 OpReturn
226 OpFunctionEnd
227 %11 = OpFunction %6 None %8
228 %9 = OpFunctionParameter %7
229 %10 = OpFunctionParameter %7
230 %12 = OpLabel
231 %23 = OpLoad %6 %9
232 %24 = OpLoad %6 %10
233 %25 = OpIAdd %6 %23 %24
234 OpReturnValue %25
235 OpFunctionEnd
236 %13 = OpFunction %2 DontInline %3
237 %14 = OpLabel
238 OpStore %29 %30
239 OpReturn
240 OpFunctionEnd
241 %17 = OpFunction %6 Pure %15
242 %16 = OpFunctionParameter %7
243 %18 = OpLabel
244 %32 = OpLoad %6 %16
245 %33 = OpIAdd %6 %31 %32
246 OpReturnValue %33
247 OpFunctionEnd
248 %21 = OpFunction %6 DontInline %8
249 %19 = OpFunctionParameter %7
250 %20 = OpFunctionParameter %7
251 %22 = OpLabel
252 %36 = OpLoad %6 %19
253 %37 = OpLoad %6 %20
254 %38 = OpIMul %6 %36 %37
255 OpReturnValue %38
256 OpFunctionEnd
257 )";
258 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
259 }
260
261 } // namespace
262 } // namespace fuzz
263 } // namespace spvtools
264