1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 Vasyl Teliman
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_add_parameter.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
19fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace fuzz {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, NonPointerBasicTest) {
26fd4e5da5Sopenharmony_ci  std::string shader = R"(
27fd4e5da5Sopenharmony_ci               OpCapability Shader
28fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
29fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
30fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
31fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
32fd4e5da5Sopenharmony_ci               OpSource ESSL 310
33fd4e5da5Sopenharmony_ci               OpName %4 "main"
34fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
35fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
36fd4e5da5Sopenharmony_ci         %11 = OpTypeInt 32 1
37fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
38fd4e5da5Sopenharmony_ci         %51 = OpConstant %11 2
39fd4e5da5Sopenharmony_ci         %52 = OpTypeArray %16 %51
40fd4e5da5Sopenharmony_ci         %53 = OpConstant %16 7
41fd4e5da5Sopenharmony_ci         %54 = OpConstantComposite %52 %53 %53
42fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
43fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %7 %7
44fd4e5da5Sopenharmony_ci          %8 = OpConstant %11 23
45fd4e5da5Sopenharmony_ci         %12 = OpConstantTrue %7
46fd4e5da5Sopenharmony_ci         %15 = OpTypeFunction %2 %16
47fd4e5da5Sopenharmony_ci         %24 = OpTypeFunction %2 %16 %7
48fd4e5da5Sopenharmony_ci         %31 = OpTypeStruct %7 %11
49fd4e5da5Sopenharmony_ci         %32 = OpConstant %16 23
50fd4e5da5Sopenharmony_ci         %33 = OpConstantComposite %31 %12 %8
51fd4e5da5Sopenharmony_ci         %41 = OpTypeStruct %11 %16
52fd4e5da5Sopenharmony_ci         %42 = OpConstantComposite %41 %8 %32
53fd4e5da5Sopenharmony_ci         %43 = OpTypeFunction %2 %41
54fd4e5da5Sopenharmony_ci         %44 = OpTypeFunction %2 %41 %7
55fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
56fd4e5da5Sopenharmony_ci          %5 = OpLabel
57fd4e5da5Sopenharmony_ci         %13 = OpFunctionCall %7 %9 %12
58fd4e5da5Sopenharmony_ci               OpReturn
59fd4e5da5Sopenharmony_ci               OpFunctionEnd
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ci          ; adjust type of the function in-place
62fd4e5da5Sopenharmony_ci          %9 = OpFunction %7 None %6
63fd4e5da5Sopenharmony_ci         %14 = OpFunctionParameter %7
64fd4e5da5Sopenharmony_ci         %10 = OpLabel
65fd4e5da5Sopenharmony_ci               OpReturnValue %12
66fd4e5da5Sopenharmony_ci               OpFunctionEnd
67fd4e5da5Sopenharmony_ci
68fd4e5da5Sopenharmony_ci         ; reuse an existing function type
69fd4e5da5Sopenharmony_ci         %17 = OpFunction %2 None %15
70fd4e5da5Sopenharmony_ci         %18 = OpFunctionParameter %16
71fd4e5da5Sopenharmony_ci         %19 = OpLabel
72fd4e5da5Sopenharmony_ci               OpReturn
73fd4e5da5Sopenharmony_ci               OpFunctionEnd
74fd4e5da5Sopenharmony_ci         %20 = OpFunction %2 None %15
75fd4e5da5Sopenharmony_ci         %21 = OpFunctionParameter %16
76fd4e5da5Sopenharmony_ci         %22 = OpLabel
77fd4e5da5Sopenharmony_ci               OpReturn
78fd4e5da5Sopenharmony_ci               OpFunctionEnd
79fd4e5da5Sopenharmony_ci         %25 = OpFunction %2 None %24
80fd4e5da5Sopenharmony_ci         %26 = OpFunctionParameter %16
81fd4e5da5Sopenharmony_ci         %27 = OpFunctionParameter %7
82fd4e5da5Sopenharmony_ci         %28 = OpLabel
83fd4e5da5Sopenharmony_ci               OpReturn
84fd4e5da5Sopenharmony_ci               OpFunctionEnd
85fd4e5da5Sopenharmony_ci
86fd4e5da5Sopenharmony_ci         ; create a new function type
87fd4e5da5Sopenharmony_ci         %29 = OpFunction %2 None %3
88fd4e5da5Sopenharmony_ci         %30 = OpLabel
89fd4e5da5Sopenharmony_ci               OpReturn
90fd4e5da5Sopenharmony_ci               OpFunctionEnd
91fd4e5da5Sopenharmony_ci
92fd4e5da5Sopenharmony_ci         ; don't adjust the type of the function if it creates a duplicate
93fd4e5da5Sopenharmony_ci         %34 = OpFunction %2 None %43
94fd4e5da5Sopenharmony_ci         %35 = OpFunctionParameter %41
95fd4e5da5Sopenharmony_ci         %36 = OpLabel
96fd4e5da5Sopenharmony_ci               OpReturn
97fd4e5da5Sopenharmony_ci               OpFunctionEnd
98fd4e5da5Sopenharmony_ci         %37 = OpFunction %2 None %44
99fd4e5da5Sopenharmony_ci         %38 = OpFunctionParameter %41
100fd4e5da5Sopenharmony_ci         %39 = OpFunctionParameter %7
101fd4e5da5Sopenharmony_ci         %40 = OpLabel
102fd4e5da5Sopenharmony_ci               OpReturn
103fd4e5da5Sopenharmony_ci               OpFunctionEnd
104fd4e5da5Sopenharmony_ci  )";
105fd4e5da5Sopenharmony_ci
106fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
107fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
108fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
109fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
110fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
111fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
112fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
113fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
114fd4e5da5Sopenharmony_ci  // Can't modify entry point function.
115fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(4, 60, 7, {{}}, 61)
116fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
117fd4e5da5Sopenharmony_ci
118fd4e5da5Sopenharmony_ci  // There is no function with result id 60.
119fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(60, 60, 11, {{}}, 61)
120fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ci  // Parameter id is not fresh.
123fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(9, 14, 11, {{{13, 8}}}, 61)
124fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
125fd4e5da5Sopenharmony_ci
126fd4e5da5Sopenharmony_ci  // Function type id is not fresh.
127fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 8}}}, 14)
128fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
129fd4e5da5Sopenharmony_ci
130fd4e5da5Sopenharmony_ci  // Function type id and parameter type id are equal.
131fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 8}}}, 60)
132fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
133fd4e5da5Sopenharmony_ci
134fd4e5da5Sopenharmony_ci  // Parameter's initializer doesn't exist.
135fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 60}}}, 61)
136fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
137fd4e5da5Sopenharmony_ci
138fd4e5da5Sopenharmony_ci  // Correct transformations.
139fd4e5da5Sopenharmony_ci  {
140fd4e5da5Sopenharmony_ci    TransformationAddParameter correct(9, 60, 11, {{{13, 8}}}, 61);
141fd4e5da5Sopenharmony_ci    ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
142fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
143fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
144fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
145fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(60));
146fd4e5da5Sopenharmony_ci  }
147fd4e5da5Sopenharmony_ci  {
148fd4e5da5Sopenharmony_ci    TransformationAddParameter correct(9, 68, 52, {{{13, 54}}}, 69);
149fd4e5da5Sopenharmony_ci    ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
150fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
151fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
152fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
153fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(68));
154fd4e5da5Sopenharmony_ci  }
155fd4e5da5Sopenharmony_ci  {
156fd4e5da5Sopenharmony_ci    TransformationAddParameter correct(17, 62, 7, {{}}, 63);
157fd4e5da5Sopenharmony_ci    ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
158fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
159fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
160fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
161fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(62));
162fd4e5da5Sopenharmony_ci  }
163fd4e5da5Sopenharmony_ci  {
164fd4e5da5Sopenharmony_ci    TransformationAddParameter correct(29, 64, 31, {{}}, 65);
165fd4e5da5Sopenharmony_ci    ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
166fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
167fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
168fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
169fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(64));
170fd4e5da5Sopenharmony_ci  }
171fd4e5da5Sopenharmony_ci  {
172fd4e5da5Sopenharmony_ci    TransformationAddParameter correct(34, 66, 7, {{}}, 67);
173fd4e5da5Sopenharmony_ci    ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
174fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
175fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
176fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
177fd4e5da5Sopenharmony_ci    ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(66));
178fd4e5da5Sopenharmony_ci  }
179fd4e5da5Sopenharmony_ci
180fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
181fd4e5da5Sopenharmony_ci               OpCapability Shader
182fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
183fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
184fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
185fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
186fd4e5da5Sopenharmony_ci               OpSource ESSL 310
187fd4e5da5Sopenharmony_ci               OpName %4 "main"
188fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
189fd4e5da5Sopenharmony_ci          %7 = OpTypeBool
190fd4e5da5Sopenharmony_ci         %11 = OpTypeInt 32 1
191fd4e5da5Sopenharmony_ci         %16 = OpTypeFloat 32
192fd4e5da5Sopenharmony_ci         %51 = OpConstant %11 2
193fd4e5da5Sopenharmony_ci         %52 = OpTypeArray %16 %51
194fd4e5da5Sopenharmony_ci         %53 = OpConstant %16 7
195fd4e5da5Sopenharmony_ci         %54 = OpConstantComposite %52 %53 %53
196fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
197fd4e5da5Sopenharmony_ci          %8 = OpConstant %11 23
198fd4e5da5Sopenharmony_ci         %12 = OpConstantTrue %7
199fd4e5da5Sopenharmony_ci         %15 = OpTypeFunction %2 %16
200fd4e5da5Sopenharmony_ci         %24 = OpTypeFunction %2 %16 %7
201fd4e5da5Sopenharmony_ci         %31 = OpTypeStruct %7 %11
202fd4e5da5Sopenharmony_ci         %32 = OpConstant %16 23
203fd4e5da5Sopenharmony_ci         %33 = OpConstantComposite %31 %12 %8
204fd4e5da5Sopenharmony_ci         %41 = OpTypeStruct %11 %16
205fd4e5da5Sopenharmony_ci         %42 = OpConstantComposite %41 %8 %32
206fd4e5da5Sopenharmony_ci         %44 = OpTypeFunction %2 %41 %7
207fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %7 %7 %11 %52
208fd4e5da5Sopenharmony_ci         %65 = OpTypeFunction %2 %31
209fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
210fd4e5da5Sopenharmony_ci          %5 = OpLabel
211fd4e5da5Sopenharmony_ci         %13 = OpFunctionCall %7 %9 %12 %8 %54
212fd4e5da5Sopenharmony_ci               OpReturn
213fd4e5da5Sopenharmony_ci               OpFunctionEnd
214fd4e5da5Sopenharmony_ci
215fd4e5da5Sopenharmony_ci          ; adjust type of the function in-place
216fd4e5da5Sopenharmony_ci          %9 = OpFunction %7 None %6
217fd4e5da5Sopenharmony_ci         %14 = OpFunctionParameter %7
218fd4e5da5Sopenharmony_ci         %60 = OpFunctionParameter %11
219fd4e5da5Sopenharmony_ci         %68 = OpFunctionParameter %52
220fd4e5da5Sopenharmony_ci         %10 = OpLabel
221fd4e5da5Sopenharmony_ci               OpReturnValue %12
222fd4e5da5Sopenharmony_ci               OpFunctionEnd
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ci         ; reuse an existing function type
225fd4e5da5Sopenharmony_ci         %17 = OpFunction %2 None %24
226fd4e5da5Sopenharmony_ci         %18 = OpFunctionParameter %16
227fd4e5da5Sopenharmony_ci         %62 = OpFunctionParameter %7
228fd4e5da5Sopenharmony_ci         %19 = OpLabel
229fd4e5da5Sopenharmony_ci               OpReturn
230fd4e5da5Sopenharmony_ci               OpFunctionEnd
231fd4e5da5Sopenharmony_ci         %20 = OpFunction %2 None %15
232fd4e5da5Sopenharmony_ci         %21 = OpFunctionParameter %16
233fd4e5da5Sopenharmony_ci         %22 = OpLabel
234fd4e5da5Sopenharmony_ci               OpReturn
235fd4e5da5Sopenharmony_ci               OpFunctionEnd
236fd4e5da5Sopenharmony_ci         %25 = OpFunction %2 None %24
237fd4e5da5Sopenharmony_ci         %26 = OpFunctionParameter %16
238fd4e5da5Sopenharmony_ci         %27 = OpFunctionParameter %7
239fd4e5da5Sopenharmony_ci         %28 = OpLabel
240fd4e5da5Sopenharmony_ci               OpReturn
241fd4e5da5Sopenharmony_ci               OpFunctionEnd
242fd4e5da5Sopenharmony_ci
243fd4e5da5Sopenharmony_ci         ; create a new function type
244fd4e5da5Sopenharmony_ci         %29 = OpFunction %2 None %65
245fd4e5da5Sopenharmony_ci         %64 = OpFunctionParameter %31
246fd4e5da5Sopenharmony_ci         %30 = OpLabel
247fd4e5da5Sopenharmony_ci               OpReturn
248fd4e5da5Sopenharmony_ci               OpFunctionEnd
249fd4e5da5Sopenharmony_ci
250fd4e5da5Sopenharmony_ci         ; don't adjust the type of the function if it creates a duplicate
251fd4e5da5Sopenharmony_ci         %34 = OpFunction %2 None %44
252fd4e5da5Sopenharmony_ci         %35 = OpFunctionParameter %41
253fd4e5da5Sopenharmony_ci         %66 = OpFunctionParameter %7
254fd4e5da5Sopenharmony_ci         %36 = OpLabel
255fd4e5da5Sopenharmony_ci               OpReturn
256fd4e5da5Sopenharmony_ci               OpFunctionEnd
257fd4e5da5Sopenharmony_ci         %37 = OpFunction %2 None %44
258fd4e5da5Sopenharmony_ci         %38 = OpFunctionParameter %41
259fd4e5da5Sopenharmony_ci         %39 = OpFunctionParameter %7
260fd4e5da5Sopenharmony_ci         %40 = OpLabel
261fd4e5da5Sopenharmony_ci               OpReturn
262fd4e5da5Sopenharmony_ci               OpFunctionEnd
263fd4e5da5Sopenharmony_ci  )";
264fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
265fd4e5da5Sopenharmony_ci}
266fd4e5da5Sopenharmony_ci
267fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, NonPointerNotApplicableTest) {
268fd4e5da5Sopenharmony_ci  // This types handles case of adding a new parameter of a non-pointer type
269fd4e5da5Sopenharmony_ci  // where the transformation is not applicable.
270fd4e5da5Sopenharmony_ci  std::string shader = R"(
271fd4e5da5Sopenharmony_ci               OpCapability Shader
272fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
273fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
274fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
275fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
276fd4e5da5Sopenharmony_ci               OpSource ESSL 310
277fd4e5da5Sopenharmony_ci               OpName %4 "main"
278fd4e5da5Sopenharmony_ci               OpName %6 "fun1("
279fd4e5da5Sopenharmony_ci               OpName %12 "fun2(i1;"
280fd4e5da5Sopenharmony_ci               OpName %11 "a"
281fd4e5da5Sopenharmony_ci               OpName %14 "fun3("
282fd4e5da5Sopenharmony_ci               OpName %24 "f1"
283fd4e5da5Sopenharmony_ci               OpName %27 "f2"
284fd4e5da5Sopenharmony_ci               OpName %30 "i1"
285fd4e5da5Sopenharmony_ci               OpName %31 "i2"
286fd4e5da5Sopenharmony_ci               OpName %32 "param"
287fd4e5da5Sopenharmony_ci               OpName %35 "i3"
288fd4e5da5Sopenharmony_ci               OpName %36 "param"
289fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
290fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
291fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
292fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
293fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %8 %9
294fd4e5da5Sopenharmony_ci         %18 = OpConstant %8 2
295fd4e5da5Sopenharmony_ci         %22 = OpTypeFloat 32
296fd4e5da5Sopenharmony_ci         %23 = OpTypePointer Private %22
297fd4e5da5Sopenharmony_ci         %24 = OpVariable %23 Private
298fd4e5da5Sopenharmony_ci         %25 = OpConstant %22 1
299fd4e5da5Sopenharmony_ci         %26 = OpTypePointer Function %22
300fd4e5da5Sopenharmony_ci         %28 = OpConstant %22 2
301fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
302fd4e5da5Sopenharmony_ci          %5 = OpLabel
303fd4e5da5Sopenharmony_ci         %27 = OpVariable %26 Function
304fd4e5da5Sopenharmony_ci         %30 = OpVariable %9 Function
305fd4e5da5Sopenharmony_ci         %31 = OpVariable %9 Function
306fd4e5da5Sopenharmony_ci         %32 = OpVariable %9 Function
307fd4e5da5Sopenharmony_ci         %35 = OpVariable %9 Function
308fd4e5da5Sopenharmony_ci         %36 = OpVariable %9 Function
309fd4e5da5Sopenharmony_ci               OpStore %24 %25
310fd4e5da5Sopenharmony_ci               OpStore %27 %28
311fd4e5da5Sopenharmony_ci         %29 = OpFunctionCall %2 %6
312fd4e5da5Sopenharmony_ci               OpStore %30 %18
313fd4e5da5Sopenharmony_ci         %33 = OpLoad %8 %30
314fd4e5da5Sopenharmony_ci               OpStore %32 %33
315fd4e5da5Sopenharmony_ci         %34 = OpFunctionCall %8 %12 %32
316fd4e5da5Sopenharmony_ci               OpStore %31 %34
317fd4e5da5Sopenharmony_ci         %37 = OpLoad %8 %31
318fd4e5da5Sopenharmony_ci               OpStore %36 %37
319fd4e5da5Sopenharmony_ci         %38 = OpFunctionCall %8 %12 %36
320fd4e5da5Sopenharmony_ci               OpStore %35 %38
321fd4e5da5Sopenharmony_ci         ; %39 = OpFunctionCall %2 %14
322fd4e5da5Sopenharmony_ci               OpReturn
323fd4e5da5Sopenharmony_ci               OpFunctionEnd
324fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
325fd4e5da5Sopenharmony_ci          %7 = OpLabel
326fd4e5da5Sopenharmony_ci               OpReturn
327fd4e5da5Sopenharmony_ci               OpFunctionEnd
328fd4e5da5Sopenharmony_ci         %12 = OpFunction %8 None %10
329fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9
330fd4e5da5Sopenharmony_ci         %13 = OpLabel
331fd4e5da5Sopenharmony_ci         %17 = OpLoad %8 %11
332fd4e5da5Sopenharmony_ci         %19 = OpIAdd %8 %17 %18
333fd4e5da5Sopenharmony_ci               OpReturnValue %19
334fd4e5da5Sopenharmony_ci               OpFunctionEnd
335fd4e5da5Sopenharmony_ci         %14 = OpFunction %2 None %3
336fd4e5da5Sopenharmony_ci         %15 = OpLabel
337fd4e5da5Sopenharmony_ci               OpReturn
338fd4e5da5Sopenharmony_ci               OpFunctionEnd
339fd4e5da5Sopenharmony_ci    )";
340fd4e5da5Sopenharmony_ci
341fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
342fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
343fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
344fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
345fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
346fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
347fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
348fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
349fd4e5da5Sopenharmony_ci  // Bad: Id 19 is not available in the caller that has id 34.
350fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_1(12, 50, 8,
351fd4e5da5Sopenharmony_ci                                                  {{{34, 19}, {38, 19}}}, 51);
352fd4e5da5Sopenharmony_ci
353fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
354fd4e5da5Sopenharmony_ci      transformation_bad_1.IsApplicable(context.get(), transformation_context));
355fd4e5da5Sopenharmony_ci
356fd4e5da5Sopenharmony_ci  // Bad: Id 8 does not have a type.
357fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_2(12, 50, 8,
358fd4e5da5Sopenharmony_ci                                                  {{{34, 8}, {38, 8}}}, 51);
359fd4e5da5Sopenharmony_ci
360fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
361fd4e5da5Sopenharmony_ci      transformation_bad_2.IsApplicable(context.get(), transformation_context));
362fd4e5da5Sopenharmony_ci
363fd4e5da5Sopenharmony_ci  // Bad: Types of id 25 and id 18 are different.
364fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_3(12, 50, 22,
365fd4e5da5Sopenharmony_ci                                                  {{{34, 25}, {38, 18}}}, 51);
366fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
367fd4e5da5Sopenharmony_ci      transformation_bad_3.IsApplicable(context.get(), transformation_context));
368fd4e5da5Sopenharmony_ci
369fd4e5da5Sopenharmony_ci  // Function with id 14 does not have any callers.
370fd4e5da5Sopenharmony_ci  // Bad: Id 18 is not a valid type.
371fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_4(14, 50, 18, {{}}, 51);
372fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
373fd4e5da5Sopenharmony_ci      transformation_bad_4.IsApplicable(context.get(), transformation_context));
374fd4e5da5Sopenharmony_ci
375fd4e5da5Sopenharmony_ci  // Function with id 14 does not have any callers.
376fd4e5da5Sopenharmony_ci  // Bad:  Id 3 refers to OpTypeVoid, which is not supported.
377fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_6(14, 50, 3, {{}}, 51);
378fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
379fd4e5da5Sopenharmony_ci      transformation_bad_6.IsApplicable(context.get(), transformation_context));
380fd4e5da5Sopenharmony_ci}
381fd4e5da5Sopenharmony_ci
382fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, PointerFunctionTest) {
383fd4e5da5Sopenharmony_ci  // This types handles case of adding a new parameter of a pointer type with
384fd4e5da5Sopenharmony_ci  // storage class Function.
385fd4e5da5Sopenharmony_ci  std::string shader = R"(
386fd4e5da5Sopenharmony_ci               OpCapability Shader
387fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
388fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
389fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
390fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
391fd4e5da5Sopenharmony_ci               OpSource ESSL 310
392fd4e5da5Sopenharmony_ci               OpName %4 "main"
393fd4e5da5Sopenharmony_ci               OpName %6 "fun1("
394fd4e5da5Sopenharmony_ci               OpName %12 "fun2(i1;"
395fd4e5da5Sopenharmony_ci               OpName %11 "a"
396fd4e5da5Sopenharmony_ci               OpName %14 "fun3("
397fd4e5da5Sopenharmony_ci               OpName %17 "s"
398fd4e5da5Sopenharmony_ci               OpName %24 "s"
399fd4e5da5Sopenharmony_ci               OpName %28 "f1"
400fd4e5da5Sopenharmony_ci               OpName %31 "f2"
401fd4e5da5Sopenharmony_ci               OpName %34 "i1"
402fd4e5da5Sopenharmony_ci               OpName %35 "i2"
403fd4e5da5Sopenharmony_ci               OpName %36 "param"
404fd4e5da5Sopenharmony_ci               OpName %39 "i3"
405fd4e5da5Sopenharmony_ci               OpName %40 "param"
406fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
407fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
408fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
409fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
410fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %8 %9
411fd4e5da5Sopenharmony_ci         %20 = OpConstant %8 2
412fd4e5da5Sopenharmony_ci         %25 = OpConstant %8 0
413fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
414fd4e5da5Sopenharmony_ci         %27 = OpTypePointer Private %26
415fd4e5da5Sopenharmony_ci         %28 = OpVariable %27 Private
416fd4e5da5Sopenharmony_ci         %60 = OpTypePointer Output %26
417fd4e5da5Sopenharmony_ci         %61 = OpVariable %60 Output
418fd4e5da5Sopenharmony_ci         %29 = OpConstant %26 1
419fd4e5da5Sopenharmony_ci         %30 = OpTypePointer Function %26
420fd4e5da5Sopenharmony_ci         %32 = OpConstant %26 2
421fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
422fd4e5da5Sopenharmony_ci          %5 = OpLabel
423fd4e5da5Sopenharmony_ci         %31 = OpVariable %30 Function
424fd4e5da5Sopenharmony_ci         %34 = OpVariable %9 Function
425fd4e5da5Sopenharmony_ci         %35 = OpVariable %9 Function
426fd4e5da5Sopenharmony_ci         %36 = OpVariable %9 Function
427fd4e5da5Sopenharmony_ci         %39 = OpVariable %9 Function
428fd4e5da5Sopenharmony_ci         %40 = OpVariable %9 Function
429fd4e5da5Sopenharmony_ci               OpStore %28 %29
430fd4e5da5Sopenharmony_ci               OpStore %31 %32
431fd4e5da5Sopenharmony_ci         %33 = OpFunctionCall %2 %6
432fd4e5da5Sopenharmony_ci               OpStore %34 %20
433fd4e5da5Sopenharmony_ci         %37 = OpLoad %8 %34
434fd4e5da5Sopenharmony_ci               OpStore %36 %37
435fd4e5da5Sopenharmony_ci         %38 = OpFunctionCall %8 %12 %36
436fd4e5da5Sopenharmony_ci               OpStore %35 %38
437fd4e5da5Sopenharmony_ci         %41 = OpLoad %8 %35
438fd4e5da5Sopenharmony_ci               OpStore %40 %41
439fd4e5da5Sopenharmony_ci         %42 = OpFunctionCall %8 %12 %40
440fd4e5da5Sopenharmony_ci               OpStore %39 %42
441fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %14
442fd4e5da5Sopenharmony_ci               OpReturn
443fd4e5da5Sopenharmony_ci               OpFunctionEnd
444fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
445fd4e5da5Sopenharmony_ci          %7 = OpLabel
446fd4e5da5Sopenharmony_ci               OpReturn
447fd4e5da5Sopenharmony_ci               OpFunctionEnd
448fd4e5da5Sopenharmony_ci         %12 = OpFunction %8 None %10
449fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9
450fd4e5da5Sopenharmony_ci         %13 = OpLabel
451fd4e5da5Sopenharmony_ci         %17 = OpVariable %9 Function
452fd4e5da5Sopenharmony_ci         %18 = OpLoad %8 %11
453fd4e5da5Sopenharmony_ci               OpStore %17 %18
454fd4e5da5Sopenharmony_ci         %19 = OpLoad %8 %17
455fd4e5da5Sopenharmony_ci         %21 = OpIAdd %8 %19 %20
456fd4e5da5Sopenharmony_ci               OpReturnValue %21
457fd4e5da5Sopenharmony_ci               OpFunctionEnd
458fd4e5da5Sopenharmony_ci         %14 = OpFunction %2 None %3
459fd4e5da5Sopenharmony_ci         %15 = OpLabel
460fd4e5da5Sopenharmony_ci         %24 = OpVariable %9 Function
461fd4e5da5Sopenharmony_ci               OpStore %24 %25
462fd4e5da5Sopenharmony_ci               OpReturn
463fd4e5da5Sopenharmony_ci               OpFunctionEnd
464fd4e5da5Sopenharmony_ci    )";
465fd4e5da5Sopenharmony_ci
466fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
467fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
468fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
469fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
470fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
471fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
472fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
473fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
474fd4e5da5Sopenharmony_ci  // Bad: Pointer of id 61 has storage class Output, which is not supported.
475fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_bad_1(12, 50, 60,
476fd4e5da5Sopenharmony_ci                                                  {{{38, 61}, {42, 61}}}, 51);
477fd4e5da5Sopenharmony_ci
478fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
479fd4e5da5Sopenharmony_ci      transformation_bad_1.IsApplicable(context.get(), transformation_context));
480fd4e5da5Sopenharmony_ci
481fd4e5da5Sopenharmony_ci  // Good: Local variable of id 31 is defined in the caller (main).
482fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_1(12, 50, 30,
483fd4e5da5Sopenharmony_ci                                                   {{{38, 31}, {42, 31}}}, 51);
484fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
485fd4e5da5Sopenharmony_ci                                                 transformation_context));
486fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_1, context.get(),
487fd4e5da5Sopenharmony_ci                        &transformation_context);
488fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
489fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
490fd4e5da5Sopenharmony_ci
491fd4e5da5Sopenharmony_ci  // Good: Local variable of id 34 is defined in the caller (main).
492fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_2(14, 52, 9, {{{43, 34}}}, 53);
493fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
494fd4e5da5Sopenharmony_ci                                                 transformation_context));
495fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_2, context.get(),
496fd4e5da5Sopenharmony_ci                        &transformation_context);
497fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
498fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
499fd4e5da5Sopenharmony_ci
500fd4e5da5Sopenharmony_ci  // Good: Local variable of id 39 is defined in the caller (main).
501fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_3(6, 54, 9, {{{33, 39}}}, 55);
502fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
503fd4e5da5Sopenharmony_ci                                                 transformation_context));
504fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_3, context.get(),
505fd4e5da5Sopenharmony_ci                        &transformation_context);
506fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
507fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
508fd4e5da5Sopenharmony_ci
509fd4e5da5Sopenharmony_ci  // Good: This adds another pointer parameter to the function of id 6.
510fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_4(6, 56, 30, {{{33, 31}}}, 57);
511fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_4.IsApplicable(context.get(),
512fd4e5da5Sopenharmony_ci                                                 transformation_context));
513fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_4, context.get(),
514fd4e5da5Sopenharmony_ci                        &transformation_context);
515fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
516fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
517fd4e5da5Sopenharmony_ci
518fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
519fd4e5da5Sopenharmony_ci               OpCapability Shader
520fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
521fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
522fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
523fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
524fd4e5da5Sopenharmony_ci               OpSource ESSL 310
525fd4e5da5Sopenharmony_ci               OpName %4 "main"
526fd4e5da5Sopenharmony_ci               OpName %6 "fun1("
527fd4e5da5Sopenharmony_ci               OpName %12 "fun2(i1;"
528fd4e5da5Sopenharmony_ci               OpName %11 "a"
529fd4e5da5Sopenharmony_ci               OpName %14 "fun3("
530fd4e5da5Sopenharmony_ci               OpName %17 "s"
531fd4e5da5Sopenharmony_ci               OpName %24 "s"
532fd4e5da5Sopenharmony_ci               OpName %28 "f1"
533fd4e5da5Sopenharmony_ci               OpName %31 "f2"
534fd4e5da5Sopenharmony_ci               OpName %34 "i1"
535fd4e5da5Sopenharmony_ci               OpName %35 "i2"
536fd4e5da5Sopenharmony_ci               OpName %36 "param"
537fd4e5da5Sopenharmony_ci               OpName %39 "i3"
538fd4e5da5Sopenharmony_ci               OpName %40 "param"
539fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
540fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
541fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
542fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
543fd4e5da5Sopenharmony_ci         %20 = OpConstant %8 2
544fd4e5da5Sopenharmony_ci         %25 = OpConstant %8 0
545fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
546fd4e5da5Sopenharmony_ci         %27 = OpTypePointer Private %26
547fd4e5da5Sopenharmony_ci         %28 = OpVariable %27 Private
548fd4e5da5Sopenharmony_ci         %60 = OpTypePointer Output %26
549fd4e5da5Sopenharmony_ci         %61 = OpVariable %60 Output
550fd4e5da5Sopenharmony_ci         %29 = OpConstant %26 1
551fd4e5da5Sopenharmony_ci         %30 = OpTypePointer Function %26
552fd4e5da5Sopenharmony_ci         %32 = OpConstant %26 2
553fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %8 %9 %30
554fd4e5da5Sopenharmony_ci         %53 = OpTypeFunction %2 %9
555fd4e5da5Sopenharmony_ci         %57 = OpTypeFunction %2 %9 %30
556fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
557fd4e5da5Sopenharmony_ci          %5 = OpLabel
558fd4e5da5Sopenharmony_ci         %31 = OpVariable %30 Function
559fd4e5da5Sopenharmony_ci         %34 = OpVariable %9 Function
560fd4e5da5Sopenharmony_ci         %35 = OpVariable %9 Function
561fd4e5da5Sopenharmony_ci         %36 = OpVariable %9 Function
562fd4e5da5Sopenharmony_ci         %39 = OpVariable %9 Function
563fd4e5da5Sopenharmony_ci         %40 = OpVariable %9 Function
564fd4e5da5Sopenharmony_ci               OpStore %28 %29
565fd4e5da5Sopenharmony_ci               OpStore %31 %32
566fd4e5da5Sopenharmony_ci         %33 = OpFunctionCall %2 %6 %39 %31
567fd4e5da5Sopenharmony_ci               OpStore %34 %20
568fd4e5da5Sopenharmony_ci         %37 = OpLoad %8 %34
569fd4e5da5Sopenharmony_ci               OpStore %36 %37
570fd4e5da5Sopenharmony_ci         %38 = OpFunctionCall %8 %12 %36 %31
571fd4e5da5Sopenharmony_ci               OpStore %35 %38
572fd4e5da5Sopenharmony_ci         %41 = OpLoad %8 %35
573fd4e5da5Sopenharmony_ci               OpStore %40 %41
574fd4e5da5Sopenharmony_ci         %42 = OpFunctionCall %8 %12 %40 %31
575fd4e5da5Sopenharmony_ci               OpStore %39 %42
576fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %14 %34
577fd4e5da5Sopenharmony_ci               OpReturn
578fd4e5da5Sopenharmony_ci               OpFunctionEnd
579fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %57
580fd4e5da5Sopenharmony_ci         %54 = OpFunctionParameter %9
581fd4e5da5Sopenharmony_ci         %56 = OpFunctionParameter %30
582fd4e5da5Sopenharmony_ci          %7 = OpLabel
583fd4e5da5Sopenharmony_ci               OpReturn
584fd4e5da5Sopenharmony_ci               OpFunctionEnd
585fd4e5da5Sopenharmony_ci         %12 = OpFunction %8 None %10
586fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9
587fd4e5da5Sopenharmony_ci         %50 = OpFunctionParameter %30
588fd4e5da5Sopenharmony_ci         %13 = OpLabel
589fd4e5da5Sopenharmony_ci         %17 = OpVariable %9 Function
590fd4e5da5Sopenharmony_ci         %18 = OpLoad %8 %11
591fd4e5da5Sopenharmony_ci               OpStore %17 %18
592fd4e5da5Sopenharmony_ci         %19 = OpLoad %8 %17
593fd4e5da5Sopenharmony_ci         %21 = OpIAdd %8 %19 %20
594fd4e5da5Sopenharmony_ci               OpReturnValue %21
595fd4e5da5Sopenharmony_ci               OpFunctionEnd
596fd4e5da5Sopenharmony_ci         %14 = OpFunction %2 None %53
597fd4e5da5Sopenharmony_ci         %52 = OpFunctionParameter %9
598fd4e5da5Sopenharmony_ci         %15 = OpLabel
599fd4e5da5Sopenharmony_ci         %24 = OpVariable %9 Function
600fd4e5da5Sopenharmony_ci               OpStore %24 %25
601fd4e5da5Sopenharmony_ci               OpReturn
602fd4e5da5Sopenharmony_ci               OpFunctionEnd
603fd4e5da5Sopenharmony_ci  )";
604fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
605fd4e5da5Sopenharmony_ci}
606fd4e5da5Sopenharmony_ci
607fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, PointerPrivateWorkgroupTest) {
608fd4e5da5Sopenharmony_ci  // This types handles case of adding a new parameter of a pointer type with
609fd4e5da5Sopenharmony_ci  // storage class Private or Workgroup.
610fd4e5da5Sopenharmony_ci  std::string shader = R"(
611fd4e5da5Sopenharmony_ci               OpCapability Shader
612fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
613fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
614fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
615fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
616fd4e5da5Sopenharmony_ci               OpSource ESSL 310
617fd4e5da5Sopenharmony_ci               OpName %4 "main"
618fd4e5da5Sopenharmony_ci               OpName %6 "fun1("
619fd4e5da5Sopenharmony_ci               OpName %12 "fun2(i1;"
620fd4e5da5Sopenharmony_ci               OpName %11 "a"
621fd4e5da5Sopenharmony_ci               OpName %14 "fun3("
622fd4e5da5Sopenharmony_ci               OpName %17 "s"
623fd4e5da5Sopenharmony_ci               OpName %24 "s"
624fd4e5da5Sopenharmony_ci               OpName %28 "f1"
625fd4e5da5Sopenharmony_ci               OpName %31 "f2"
626fd4e5da5Sopenharmony_ci               OpName %34 "i1"
627fd4e5da5Sopenharmony_ci               OpName %35 "i2"
628fd4e5da5Sopenharmony_ci               OpName %36 "param"
629fd4e5da5Sopenharmony_ci               OpName %39 "i3"
630fd4e5da5Sopenharmony_ci               OpName %40 "param"
631fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
632fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
633fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
634fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
635fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %8 %9
636fd4e5da5Sopenharmony_ci         %20 = OpConstant %8 2
637fd4e5da5Sopenharmony_ci         %25 = OpConstant %8 0
638fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
639fd4e5da5Sopenharmony_ci         %27 = OpTypePointer Private %26
640fd4e5da5Sopenharmony_ci         %28 = OpVariable %27 Private
641fd4e5da5Sopenharmony_ci         %60 = OpTypePointer Workgroup %26
642fd4e5da5Sopenharmony_ci         %61 = OpVariable %60 Workgroup
643fd4e5da5Sopenharmony_ci         %29 = OpConstant %26 1
644fd4e5da5Sopenharmony_ci         %30 = OpTypePointer Function %26
645fd4e5da5Sopenharmony_ci         %32 = OpConstant %26 2
646fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
647fd4e5da5Sopenharmony_ci          %5 = OpLabel
648fd4e5da5Sopenharmony_ci         %31 = OpVariable %30 Function
649fd4e5da5Sopenharmony_ci         %34 = OpVariable %9 Function
650fd4e5da5Sopenharmony_ci         %35 = OpVariable %9 Function
651fd4e5da5Sopenharmony_ci         %36 = OpVariable %9 Function
652fd4e5da5Sopenharmony_ci         %39 = OpVariable %9 Function
653fd4e5da5Sopenharmony_ci         %40 = OpVariable %9 Function
654fd4e5da5Sopenharmony_ci               OpStore %28 %29
655fd4e5da5Sopenharmony_ci               OpStore %31 %32
656fd4e5da5Sopenharmony_ci         %33 = OpFunctionCall %2 %6
657fd4e5da5Sopenharmony_ci               OpStore %34 %20
658fd4e5da5Sopenharmony_ci         %37 = OpLoad %8 %34
659fd4e5da5Sopenharmony_ci               OpStore %36 %37
660fd4e5da5Sopenharmony_ci         %38 = OpFunctionCall %8 %12 %36
661fd4e5da5Sopenharmony_ci               OpStore %35 %38
662fd4e5da5Sopenharmony_ci         %41 = OpLoad %8 %35
663fd4e5da5Sopenharmony_ci               OpStore %40 %41
664fd4e5da5Sopenharmony_ci         %42 = OpFunctionCall %8 %12 %40
665fd4e5da5Sopenharmony_ci               OpStore %39 %42
666fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %14
667fd4e5da5Sopenharmony_ci               OpReturn
668fd4e5da5Sopenharmony_ci               OpFunctionEnd
669fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
670fd4e5da5Sopenharmony_ci          %7 = OpLabel
671fd4e5da5Sopenharmony_ci               OpReturn
672fd4e5da5Sopenharmony_ci               OpFunctionEnd
673fd4e5da5Sopenharmony_ci         %12 = OpFunction %8 None %10
674fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9
675fd4e5da5Sopenharmony_ci         %13 = OpLabel
676fd4e5da5Sopenharmony_ci         %17 = OpVariable %9 Function
677fd4e5da5Sopenharmony_ci         %18 = OpLoad %8 %11
678fd4e5da5Sopenharmony_ci               OpStore %17 %18
679fd4e5da5Sopenharmony_ci         %19 = OpLoad %8 %17
680fd4e5da5Sopenharmony_ci         %21 = OpIAdd %8 %19 %20
681fd4e5da5Sopenharmony_ci               OpReturnValue %21
682fd4e5da5Sopenharmony_ci               OpFunctionEnd
683fd4e5da5Sopenharmony_ci         %14 = OpFunction %2 None %3
684fd4e5da5Sopenharmony_ci         %15 = OpLabel
685fd4e5da5Sopenharmony_ci         %24 = OpVariable %9 Function
686fd4e5da5Sopenharmony_ci               OpStore %24 %25
687fd4e5da5Sopenharmony_ci               OpReturn
688fd4e5da5Sopenharmony_ci               OpFunctionEnd
689fd4e5da5Sopenharmony_ci    )";
690fd4e5da5Sopenharmony_ci
691fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
692fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
693fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
694fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
695fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
696fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
697fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
698fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
699fd4e5da5Sopenharmony_ci  // Good: Global variable of id 28 (storage class Private) is defined in the
700fd4e5da5Sopenharmony_ci  // caller (main).
701fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_1(12, 70, 27,
702fd4e5da5Sopenharmony_ci                                                   {{{38, 28}, {42, 28}}}, 71);
703fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
704fd4e5da5Sopenharmony_ci                                                 transformation_context));
705fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_1, context.get(),
706fd4e5da5Sopenharmony_ci                        &transformation_context);
707fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
708fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
709fd4e5da5Sopenharmony_ci
710fd4e5da5Sopenharmony_ci  // Good: Global variable of id 61 is (storage class Workgroup) is defined in
711fd4e5da5Sopenharmony_ci  // the caller (main).
712fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_2(12, 72, 27,
713fd4e5da5Sopenharmony_ci                                                   {{{38, 28}, {42, 28}}}, 73);
714fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
715fd4e5da5Sopenharmony_ci                                                 transformation_context));
716fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_2, context.get(),
717fd4e5da5Sopenharmony_ci                        &transformation_context);
718fd4e5da5Sopenharmony_ci
719fd4e5da5Sopenharmony_ci  // Good: Global variable of id 28 (storage class Private) is defined in the
720fd4e5da5Sopenharmony_ci  // caller (main).
721fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_3(6, 74, 27, {{{33, 28}}}, 75);
722fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
723fd4e5da5Sopenharmony_ci                                                 transformation_context));
724fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_3, context.get(),
725fd4e5da5Sopenharmony_ci                        &transformation_context);
726fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
727fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
728fd4e5da5Sopenharmony_ci
729fd4e5da5Sopenharmony_ci  // Good: Global variable of id 61 is (storage class Workgroup) is defined in
730fd4e5da5Sopenharmony_ci  // the caller (main).
731fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_4(6, 76, 60, {{{33, 61}}}, 77);
732fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_4.IsApplicable(context.get(),
733fd4e5da5Sopenharmony_ci                                                 transformation_context));
734fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_4, context.get(),
735fd4e5da5Sopenharmony_ci                        &transformation_context);
736fd4e5da5Sopenharmony_ci
737fd4e5da5Sopenharmony_ci  // Good: Global variable of id 28 (storage class Private) is defined in the
738fd4e5da5Sopenharmony_ci  // caller (main).
739fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_5(14, 78, 27, {{{43, 28}}},
740fd4e5da5Sopenharmony_ci                                                   79);
741fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_5.IsApplicable(context.get(),
742fd4e5da5Sopenharmony_ci                                                 transformation_context));
743fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_5, context.get(),
744fd4e5da5Sopenharmony_ci                        &transformation_context);
745fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
746fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
747fd4e5da5Sopenharmony_ci
748fd4e5da5Sopenharmony_ci  // Good: Global variable of id 61 is (storage class Workgroup) is defined in
749fd4e5da5Sopenharmony_ci  // the caller (main).
750fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_6(14, 80, 60, {{{43, 61}}},
751fd4e5da5Sopenharmony_ci                                                   81);
752fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_6.IsApplicable(context.get(),
753fd4e5da5Sopenharmony_ci                                                 transformation_context));
754fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_6, context.get(),
755fd4e5da5Sopenharmony_ci                        &transformation_context);
756fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
757fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
758fd4e5da5Sopenharmony_ci
759fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
760fd4e5da5Sopenharmony_ci               OpCapability Shader
761fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
762fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
763fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
764fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
765fd4e5da5Sopenharmony_ci               OpSource ESSL 310
766fd4e5da5Sopenharmony_ci               OpName %4 "main"
767fd4e5da5Sopenharmony_ci               OpName %6 "fun1("
768fd4e5da5Sopenharmony_ci               OpName %12 "fun2(i1;"
769fd4e5da5Sopenharmony_ci               OpName %11 "a"
770fd4e5da5Sopenharmony_ci               OpName %14 "fun3("
771fd4e5da5Sopenharmony_ci               OpName %17 "s"
772fd4e5da5Sopenharmony_ci               OpName %24 "s"
773fd4e5da5Sopenharmony_ci               OpName %28 "f1"
774fd4e5da5Sopenharmony_ci               OpName %31 "f2"
775fd4e5da5Sopenharmony_ci               OpName %34 "i1"
776fd4e5da5Sopenharmony_ci               OpName %35 "i2"
777fd4e5da5Sopenharmony_ci               OpName %36 "param"
778fd4e5da5Sopenharmony_ci               OpName %39 "i3"
779fd4e5da5Sopenharmony_ci               OpName %40 "param"
780fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
781fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
782fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
783fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
784fd4e5da5Sopenharmony_ci         %20 = OpConstant %8 2
785fd4e5da5Sopenharmony_ci         %25 = OpConstant %8 0
786fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
787fd4e5da5Sopenharmony_ci         %27 = OpTypePointer Private %26
788fd4e5da5Sopenharmony_ci         %28 = OpVariable %27 Private
789fd4e5da5Sopenharmony_ci         %60 = OpTypePointer Workgroup %26
790fd4e5da5Sopenharmony_ci         %61 = OpVariable %60 Workgroup
791fd4e5da5Sopenharmony_ci         %29 = OpConstant %26 1
792fd4e5da5Sopenharmony_ci         %30 = OpTypePointer Function %26
793fd4e5da5Sopenharmony_ci         %32 = OpConstant %26 2
794fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %8 %9 %27 %27
795fd4e5da5Sopenharmony_ci         %75 = OpTypeFunction %2 %27 %60
796fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
797fd4e5da5Sopenharmony_ci          %5 = OpLabel
798fd4e5da5Sopenharmony_ci         %31 = OpVariable %30 Function
799fd4e5da5Sopenharmony_ci         %34 = OpVariable %9 Function
800fd4e5da5Sopenharmony_ci         %35 = OpVariable %9 Function
801fd4e5da5Sopenharmony_ci         %36 = OpVariable %9 Function
802fd4e5da5Sopenharmony_ci         %39 = OpVariable %9 Function
803fd4e5da5Sopenharmony_ci         %40 = OpVariable %9 Function
804fd4e5da5Sopenharmony_ci               OpStore %28 %29
805fd4e5da5Sopenharmony_ci               OpStore %31 %32
806fd4e5da5Sopenharmony_ci         %33 = OpFunctionCall %2 %6 %28 %61
807fd4e5da5Sopenharmony_ci               OpStore %34 %20
808fd4e5da5Sopenharmony_ci         %37 = OpLoad %8 %34
809fd4e5da5Sopenharmony_ci               OpStore %36 %37
810fd4e5da5Sopenharmony_ci         %38 = OpFunctionCall %8 %12 %36 %28 %28
811fd4e5da5Sopenharmony_ci               OpStore %35 %38
812fd4e5da5Sopenharmony_ci         %41 = OpLoad %8 %35
813fd4e5da5Sopenharmony_ci               OpStore %40 %41
814fd4e5da5Sopenharmony_ci         %42 = OpFunctionCall %8 %12 %40 %28 %28
815fd4e5da5Sopenharmony_ci               OpStore %39 %42
816fd4e5da5Sopenharmony_ci         %43 = OpFunctionCall %2 %14 %28 %61
817fd4e5da5Sopenharmony_ci               OpReturn
818fd4e5da5Sopenharmony_ci               OpFunctionEnd
819fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %75
820fd4e5da5Sopenharmony_ci         %74 = OpFunctionParameter %27
821fd4e5da5Sopenharmony_ci         %76 = OpFunctionParameter %60
822fd4e5da5Sopenharmony_ci          %7 = OpLabel
823fd4e5da5Sopenharmony_ci               OpReturn
824fd4e5da5Sopenharmony_ci               OpFunctionEnd
825fd4e5da5Sopenharmony_ci         %12 = OpFunction %8 None %10
826fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9
827fd4e5da5Sopenharmony_ci         %70 = OpFunctionParameter %27
828fd4e5da5Sopenharmony_ci         %72 = OpFunctionParameter %27
829fd4e5da5Sopenharmony_ci         %13 = OpLabel
830fd4e5da5Sopenharmony_ci         %17 = OpVariable %9 Function
831fd4e5da5Sopenharmony_ci         %18 = OpLoad %8 %11
832fd4e5da5Sopenharmony_ci               OpStore %17 %18
833fd4e5da5Sopenharmony_ci         %19 = OpLoad %8 %17
834fd4e5da5Sopenharmony_ci         %21 = OpIAdd %8 %19 %20
835fd4e5da5Sopenharmony_ci               OpReturnValue %21
836fd4e5da5Sopenharmony_ci               OpFunctionEnd
837fd4e5da5Sopenharmony_ci         %14 = OpFunction %2 None %75
838fd4e5da5Sopenharmony_ci         %78 = OpFunctionParameter %27
839fd4e5da5Sopenharmony_ci         %80 = OpFunctionParameter %60
840fd4e5da5Sopenharmony_ci         %15 = OpLabel
841fd4e5da5Sopenharmony_ci         %24 = OpVariable %9 Function
842fd4e5da5Sopenharmony_ci               OpStore %24 %25
843fd4e5da5Sopenharmony_ci               OpReturn
844fd4e5da5Sopenharmony_ci               OpFunctionEnd
845fd4e5da5Sopenharmony_ci  )";
846fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
847fd4e5da5Sopenharmony_ci}
848fd4e5da5Sopenharmony_ci
849fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, PointerMoreEntriesInMapTest) {
850fd4e5da5Sopenharmony_ci  // This types handles case where call_parameter_id has an entry for at least
851fd4e5da5Sopenharmony_ci  // every caller (there are more entries than it is necessary).
852fd4e5da5Sopenharmony_ci  std::string shader = R"(
853fd4e5da5Sopenharmony_ci               OpCapability Shader
854fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
855fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
856fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
857fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
858fd4e5da5Sopenharmony_ci               OpSource ESSL 310
859fd4e5da5Sopenharmony_ci               OpName %4 "main"
860fd4e5da5Sopenharmony_ci               OpName %10 "fun(i1;"
861fd4e5da5Sopenharmony_ci               OpName %9 "a"
862fd4e5da5Sopenharmony_ci               OpName %12 "s"
863fd4e5da5Sopenharmony_ci               OpName %19 "i1"
864fd4e5da5Sopenharmony_ci               OpName %21 "i2"
865fd4e5da5Sopenharmony_ci               OpName %22 "i3"
866fd4e5da5Sopenharmony_ci               OpName %24 "i4"
867fd4e5da5Sopenharmony_ci               OpName %25 "param"
868fd4e5da5Sopenharmony_ci               OpName %28 "i5"
869fd4e5da5Sopenharmony_ci               OpName %29 "param"
870fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
871fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
872fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
873fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
874fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %6 %7
875fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 2
876fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 1
877fd4e5da5Sopenharmony_ci         %23 = OpConstant %6 3
878fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
879fd4e5da5Sopenharmony_ci          %5 = OpLabel
880fd4e5da5Sopenharmony_ci         %19 = OpVariable %7 Function
881fd4e5da5Sopenharmony_ci         %21 = OpVariable %7 Function
882fd4e5da5Sopenharmony_ci         %22 = OpVariable %7 Function
883fd4e5da5Sopenharmony_ci         %24 = OpVariable %7 Function
884fd4e5da5Sopenharmony_ci         %25 = OpVariable %7 Function
885fd4e5da5Sopenharmony_ci         %28 = OpVariable %7 Function
886fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
887fd4e5da5Sopenharmony_ci               OpStore %19 %20
888fd4e5da5Sopenharmony_ci               OpStore %21 %15
889fd4e5da5Sopenharmony_ci               OpStore %22 %23
890fd4e5da5Sopenharmony_ci         %26 = OpLoad %6 %19
891fd4e5da5Sopenharmony_ci               OpStore %25 %26
892fd4e5da5Sopenharmony_ci         %27 = OpFunctionCall %6 %10 %25
893fd4e5da5Sopenharmony_ci               OpStore %24 %27
894fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %21
895fd4e5da5Sopenharmony_ci               OpStore %29 %30
896fd4e5da5Sopenharmony_ci         %31 = OpFunctionCall %6 %10 %29
897fd4e5da5Sopenharmony_ci               OpStore %28 %31
898fd4e5da5Sopenharmony_ci               OpReturn
899fd4e5da5Sopenharmony_ci               OpFunctionEnd
900fd4e5da5Sopenharmony_ci         %10 = OpFunction %6 None %8
901fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
902fd4e5da5Sopenharmony_ci         %11 = OpLabel
903fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function
904fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %9
905fd4e5da5Sopenharmony_ci               OpStore %12 %13
906fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %12
907fd4e5da5Sopenharmony_ci         %16 = OpIAdd %6 %14 %15
908fd4e5da5Sopenharmony_ci               OpReturnValue %16
909fd4e5da5Sopenharmony_ci               OpFunctionEnd
910fd4e5da5Sopenharmony_ci    )";
911fd4e5da5Sopenharmony_ci
912fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
913fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
914fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
915fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
916fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
917fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
918fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
919fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
920fd4e5da5Sopenharmony_ci  // Good: Local variable of id 21 is defined in every caller (id 27 and id 31).
921fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_1(
922fd4e5da5Sopenharmony_ci      10, 70, 7, {{{27, 21}, {31, 21}, {30, 21}}}, 71);
923fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
924fd4e5da5Sopenharmony_ci                                                 transformation_context));
925fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_1, context.get(),
926fd4e5da5Sopenharmony_ci                        &transformation_context);
927fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
928fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
929fd4e5da5Sopenharmony_ci
930fd4e5da5Sopenharmony_ci  // Good: Local variable of id 28 is defined in every caller (id 27 and id 31).
931fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_2(
932fd4e5da5Sopenharmony_ci      10, 72, 7, {{{27, 28}, {31, 28}, {14, 21}, {16, 14}}}, 73);
933fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
934fd4e5da5Sopenharmony_ci                                                 transformation_context));
935fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_2, context.get(),
936fd4e5da5Sopenharmony_ci                        &transformation_context);
937fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
938fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
939fd4e5da5Sopenharmony_ci
940fd4e5da5Sopenharmony_ci  std::string expected_shader = R"(
941fd4e5da5Sopenharmony_ci              OpCapability Shader
942fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
943fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
944fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
945fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
946fd4e5da5Sopenharmony_ci               OpSource ESSL 310
947fd4e5da5Sopenharmony_ci               OpName %4 "main"
948fd4e5da5Sopenharmony_ci               OpName %10 "fun(i1;"
949fd4e5da5Sopenharmony_ci               OpName %9 "a"
950fd4e5da5Sopenharmony_ci               OpName %12 "s"
951fd4e5da5Sopenharmony_ci               OpName %19 "i1"
952fd4e5da5Sopenharmony_ci               OpName %21 "i2"
953fd4e5da5Sopenharmony_ci               OpName %22 "i3"
954fd4e5da5Sopenharmony_ci               OpName %24 "i4"
955fd4e5da5Sopenharmony_ci               OpName %25 "param"
956fd4e5da5Sopenharmony_ci               OpName %28 "i5"
957fd4e5da5Sopenharmony_ci               OpName %29 "param"
958fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
959fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
960fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
961fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
962fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 2
963fd4e5da5Sopenharmony_ci         %20 = OpConstant %6 1
964fd4e5da5Sopenharmony_ci         %23 = OpConstant %6 3
965fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %6 %7 %7 %7
966fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
967fd4e5da5Sopenharmony_ci          %5 = OpLabel
968fd4e5da5Sopenharmony_ci         %19 = OpVariable %7 Function
969fd4e5da5Sopenharmony_ci         %21 = OpVariable %7 Function
970fd4e5da5Sopenharmony_ci         %22 = OpVariable %7 Function
971fd4e5da5Sopenharmony_ci         %24 = OpVariable %7 Function
972fd4e5da5Sopenharmony_ci         %25 = OpVariable %7 Function
973fd4e5da5Sopenharmony_ci         %28 = OpVariable %7 Function
974fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
975fd4e5da5Sopenharmony_ci               OpStore %19 %20
976fd4e5da5Sopenharmony_ci               OpStore %21 %15
977fd4e5da5Sopenharmony_ci               OpStore %22 %23
978fd4e5da5Sopenharmony_ci         %26 = OpLoad %6 %19
979fd4e5da5Sopenharmony_ci               OpStore %25 %26
980fd4e5da5Sopenharmony_ci         %27 = OpFunctionCall %6 %10 %25 %21 %28
981fd4e5da5Sopenharmony_ci               OpStore %24 %27
982fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %21
983fd4e5da5Sopenharmony_ci               OpStore %29 %30
984fd4e5da5Sopenharmony_ci         %31 = OpFunctionCall %6 %10 %29 %21 %28
985fd4e5da5Sopenharmony_ci               OpStore %28 %31
986fd4e5da5Sopenharmony_ci               OpReturn
987fd4e5da5Sopenharmony_ci               OpFunctionEnd
988fd4e5da5Sopenharmony_ci         %10 = OpFunction %6 None %8
989fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
990fd4e5da5Sopenharmony_ci         %70 = OpFunctionParameter %7
991fd4e5da5Sopenharmony_ci         %72 = OpFunctionParameter %7
992fd4e5da5Sopenharmony_ci         %11 = OpLabel
993fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function
994fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %9
995fd4e5da5Sopenharmony_ci               OpStore %12 %13
996fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %12
997fd4e5da5Sopenharmony_ci         %16 = OpIAdd %6 %14 %15
998fd4e5da5Sopenharmony_ci               OpReturnValue %16
999fd4e5da5Sopenharmony_ci               OpFunctionEnd
1000fd4e5da5Sopenharmony_ci    )";
1001fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1002fd4e5da5Sopenharmony_ci}
1003fd4e5da5Sopenharmony_ci
1004fd4e5da5Sopenharmony_ciTEST(TransformationAddParameterTest, PointeeValueIsIrrelevantTest) {
1005fd4e5da5Sopenharmony_ci  // This test checks if the transformation has correctly applied the
1006fd4e5da5Sopenharmony_ci  // PointeeValueIsIrrelevant fact for new pointer parameters.
1007fd4e5da5Sopenharmony_ci  std::string shader = R"(
1008fd4e5da5Sopenharmony_ci               OpCapability Shader
1009fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
1010fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1011fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
1012fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
1013fd4e5da5Sopenharmony_ci               OpSource ESSL 310
1014fd4e5da5Sopenharmony_ci               OpName %4 "main"
1015fd4e5da5Sopenharmony_ci               OpName %10 "fun(i1;"
1016fd4e5da5Sopenharmony_ci               OpName %9 "a"
1017fd4e5da5Sopenharmony_ci               OpName %12 "s"
1018fd4e5da5Sopenharmony_ci               OpName %20 "b"
1019fd4e5da5Sopenharmony_ci               OpName %22 "i1"
1020fd4e5da5Sopenharmony_ci               OpName %24 "i2"
1021fd4e5da5Sopenharmony_ci               OpName %25 "i3"
1022fd4e5da5Sopenharmony_ci               OpName %26 "param"
1023fd4e5da5Sopenharmony_ci               OpName %29 "i4"
1024fd4e5da5Sopenharmony_ci               OpName %30 "param"
1025fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
1026fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
1027fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
1028fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
1029fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Workgroup %6
1030fd4e5da5Sopenharmony_ci         %51 = OpVariable %50 Workgroup
1031fd4e5da5Sopenharmony_ci          %8 = OpTypeFunction %6 %7
1032fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 2
1033fd4e5da5Sopenharmony_ci         %19 = OpTypePointer Private %6
1034fd4e5da5Sopenharmony_ci         %20 = OpVariable %19 Private
1035fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 0
1036fd4e5da5Sopenharmony_ci         %23 = OpConstant %6 1
1037fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
1038fd4e5da5Sopenharmony_ci          %5 = OpLabel
1039fd4e5da5Sopenharmony_ci         %22 = OpVariable %7 Function
1040fd4e5da5Sopenharmony_ci         %24 = OpVariable %7 Function
1041fd4e5da5Sopenharmony_ci         %25 = OpVariable %7 Function
1042fd4e5da5Sopenharmony_ci         %26 = OpVariable %7 Function
1043fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
1044fd4e5da5Sopenharmony_ci         %30 = OpVariable %7 Function
1045fd4e5da5Sopenharmony_ci               OpStore %20 %21
1046fd4e5da5Sopenharmony_ci               OpStore %22 %23
1047fd4e5da5Sopenharmony_ci               OpStore %24 %15
1048fd4e5da5Sopenharmony_ci         %27 = OpLoad %6 %22
1049fd4e5da5Sopenharmony_ci               OpStore %26 %27
1050fd4e5da5Sopenharmony_ci         %28 = OpFunctionCall %6 %10 %26
1051fd4e5da5Sopenharmony_ci               OpStore %25 %28
1052fd4e5da5Sopenharmony_ci         %31 = OpLoad %6 %24
1053fd4e5da5Sopenharmony_ci               OpStore %30 %31
1054fd4e5da5Sopenharmony_ci         %32 = OpFunctionCall %6 %10 %30
1055fd4e5da5Sopenharmony_ci               OpStore %29 %32
1056fd4e5da5Sopenharmony_ci               OpReturn
1057fd4e5da5Sopenharmony_ci               OpFunctionEnd
1058fd4e5da5Sopenharmony_ci         %10 = OpFunction %6 None %8
1059fd4e5da5Sopenharmony_ci          %9 = OpFunctionParameter %7
1060fd4e5da5Sopenharmony_ci         %11 = OpLabel
1061fd4e5da5Sopenharmony_ci         %12 = OpVariable %7 Function
1062fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %9
1063fd4e5da5Sopenharmony_ci               OpStore %12 %13
1064fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %12
1065fd4e5da5Sopenharmony_ci         %16 = OpIAdd %6 %14 %15
1066fd4e5da5Sopenharmony_ci               OpReturnValue %16
1067fd4e5da5Sopenharmony_ci               OpFunctionEnd
1068fd4e5da5Sopenharmony_ci    )";
1069fd4e5da5Sopenharmony_ci
1070fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
1071fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
1072fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1073fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
1074fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1075fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1076fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
1077fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
1078fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_1(10, 70, 7,
1079fd4e5da5Sopenharmony_ci                                                   {{{28, 22}, {32, 22}}}, 71);
1080fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
1081fd4e5da5Sopenharmony_ci                                                 transformation_context));
1082fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_1, context.get(),
1083fd4e5da5Sopenharmony_ci                        &transformation_context);
1084fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1085fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1086fd4e5da5Sopenharmony_ci
1087fd4e5da5Sopenharmony_ci  // Check if the fact PointeeValueIsIrrelevant is set for the new parameter
1088fd4e5da5Sopenharmony_ci  // (storage class Function).
1089fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1090fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(70));
1091fd4e5da5Sopenharmony_ci
1092fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_2(10, 72, 19,
1093fd4e5da5Sopenharmony_ci                                                   {{{28, 20}, {32, 20}}}, 73);
1094fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
1095fd4e5da5Sopenharmony_ci                                                 transformation_context));
1096fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_2, context.get(),
1097fd4e5da5Sopenharmony_ci                        &transformation_context);
1098fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1099fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1100fd4e5da5Sopenharmony_ci
1101fd4e5da5Sopenharmony_ci  // Check if the fact PointeeValueIsIrrelevant is set for the new parameter
1102fd4e5da5Sopenharmony_ci  // (storage class Private).
1103fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1104fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(72));
1105fd4e5da5Sopenharmony_ci
1106fd4e5da5Sopenharmony_ci  TransformationAddParameter transformation_good_3(10, 74, 50,
1107fd4e5da5Sopenharmony_ci                                                   {{{28, 51}, {32, 51}}}, 75);
1108fd4e5da5Sopenharmony_ci  ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
1109fd4e5da5Sopenharmony_ci                                                 transformation_context));
1110fd4e5da5Sopenharmony_ci  ApplyAndCheckFreshIds(transformation_good_3, context.get(),
1111fd4e5da5Sopenharmony_ci                        &transformation_context);
1112fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1113fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
1114fd4e5da5Sopenharmony_ci
1115fd4e5da5Sopenharmony_ci  // Check if the fact PointeeValueIsIrrelevant is set for the new parameter
1116fd4e5da5Sopenharmony_ci  // (storage class Workgroup).
1117fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
1118fd4e5da5Sopenharmony_ci      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(74));
1119fd4e5da5Sopenharmony_ci}
1120fd4e5da5Sopenharmony_ci
1121fd4e5da5Sopenharmony_ci}  // namespace
1122fd4e5da5Sopenharmony_ci}  // namespace fuzz
1123fd4e5da5Sopenharmony_ci}  // namespace spvtools
1124