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(
128 36, uint32_t(spv::FunctionControlMask::MaskNone))
129 .IsApplicable(context.get(), transformation_context));
130 // Cannot add the Pure function control to %4 as it did not already have it
131 ASSERT_FALSE(TransformationSetFunctionControl(
132 4, uint32_t(spv::FunctionControlMask::Pure))
133 .IsApplicable(context.get(), transformation_context));
134 // Cannot add the Const function control to %21 as it did not already
135 // have it
136 ASSERT_FALSE(TransformationSetFunctionControl(
137 21, uint32_t(spv::FunctionControlMask::Const))
138 .IsApplicable(context.get(), transformation_context));
139
140 // Set to None, removing Const
141 TransformationSetFunctionControl transformation1(
142 11, uint32_t(spv::FunctionControlMask::MaskNone));
143 ASSERT_TRUE(
144 transformation1.IsApplicable(context.get(), transformation_context));
145 ApplyAndCheckFreshIds(transformation1, context.get(),
146 &transformation_context);
147
148 // Set to Inline; silly to do it on an entry point, but it is allowed
149 TransformationSetFunctionControl transformation2(
150 4, uint32_t(spv::FunctionControlMask::Inline));
151 ASSERT_TRUE(
152 transformation2.IsApplicable(context.get(), transformation_context));
153 ApplyAndCheckFreshIds(transformation2, context.get(),
154 &transformation_context);
155
156 // Set to Pure, removing DontInline
157 TransformationSetFunctionControl transformation3(
158 17, uint32_t(spv::FunctionControlMask::Pure));
159 ASSERT_TRUE(
160 transformation3.IsApplicable(context.get(), transformation_context));
161 ApplyAndCheckFreshIds(transformation3, context.get(),
162 &transformation_context);
163
164 // Change from Inline to DontInline
165 TransformationSetFunctionControl transformation4(
166 13, uint32_t(spv::FunctionControlMask::DontInline));
167 ASSERT_TRUE(
168 transformation4.IsApplicable(context.get(), transformation_context));
169 ApplyAndCheckFreshIds(transformation4, context.get(),
170 &transformation_context);
171
172 std::string after_transformation = R"(
173 OpCapability Shader
174 %1 = OpExtInstImport "GLSL.std.450"
175 OpMemoryModel Logical GLSL450
176 OpEntryPoint Fragment %4 "main" %54
177 OpExecutionMode %4 OriginUpperLeft
178 OpSource ESSL 310
179 OpName %4 "main"
180 OpName %11 "foo(i1;i1;"
181 OpName %9 "a"
182 OpName %10 "b"
183 OpName %13 "bar("
184 OpName %17 "baz(i1;"
185 OpName %16 "x"
186 OpName %21 "boo(i1;i1;"
187 OpName %19 "a"
188 OpName %20 "b"
189 OpName %29 "g"
190 OpName %42 "param"
191 OpName %44 "param"
192 OpName %45 "param"
193 OpName %48 "param"
194 OpName %49 "param"
195 OpName %54 "color"
196 OpDecorate %54 Location 0
197 %2 = OpTypeVoid
198 %3 = OpTypeFunction %2
199 %6 = OpTypeInt 32 1
200 %7 = OpTypePointer Function %6
201 %8 = OpTypeFunction %6 %7 %7
202 %15 = OpTypeFunction %6 %7
203 %28 = OpTypePointer Private %6
204 %29 = OpVariable %28 Private
205 %30 = OpConstant %6 2
206 %31 = OpConstant %6 5
207 %51 = OpTypeFloat 32
208 %52 = OpTypeVector %51 4
209 %53 = OpTypePointer Output %52
210 %54 = OpVariable %53 Output
211 %4 = OpFunction %2 Inline %3
212 %5 = OpLabel
213 %42 = OpVariable %7 Function
214 %44 = OpVariable %7 Function
215 %45 = OpVariable %7 Function
216 %48 = OpVariable %7 Function
217 %49 = OpVariable %7 Function
218 %41 = OpFunctionCall %2 %13
219 OpStore %42 %30
220 %43 = OpFunctionCall %6 %17 %42
221 OpStore %44 %31
222 %46 = OpLoad %6 %29
223 OpStore %45 %46
224 %47 = OpFunctionCall %6 %21 %44 %45
225 OpStore %48 %43
226 OpStore %49 %47
227 %50 = OpFunctionCall %6 %11 %48 %49
228 OpReturn
229 OpFunctionEnd
230 %11 = OpFunction %6 None %8
231 %9 = OpFunctionParameter %7
232 %10 = OpFunctionParameter %7
233 %12 = OpLabel
234 %23 = OpLoad %6 %9
235 %24 = OpLoad %6 %10
236 %25 = OpIAdd %6 %23 %24
237 OpReturnValue %25
238 OpFunctionEnd
239 %13 = OpFunction %2 DontInline %3
240 %14 = OpLabel
241 OpStore %29 %30
242 OpReturn
243 OpFunctionEnd
244 %17 = OpFunction %6 Pure %15
245 %16 = OpFunctionParameter %7
246 %18 = OpLabel
247 %32 = OpLoad %6 %16
248 %33 = OpIAdd %6 %31 %32
249 OpReturnValue %33
250 OpFunctionEnd
251 %21 = OpFunction %6 DontInline %8
252 %19 = OpFunctionParameter %7
253 %20 = OpFunctionParameter %7
254 %22 = OpLabel
255 %36 = OpLoad %6 %19
256 %37 = OpLoad %6 %20
257 %38 = OpIMul %6 %36 %37
258 OpReturnValue %38
259 OpFunctionEnd
260 )";
261 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
262 }
263
264 } // namespace
265 } // namespace fuzz
266 } // namespace spvtools
267