1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
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_store.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
19fd4e5da5Sopenharmony_ci#include "source/fuzz/instruction_descriptor.h"
20fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace fuzz {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciTEST(TransformationStoreTest, BasicTest) {
27fd4e5da5Sopenharmony_ci  std::string shader = R"(
28fd4e5da5Sopenharmony_ci               OpCapability Shader
29fd4e5da5Sopenharmony_ci               OpCapability VariablePointers
30fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
31fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
32fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %92 %52 %53
33fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
34fd4e5da5Sopenharmony_ci               OpSource ESSL 310
35fd4e5da5Sopenharmony_ci               OpDecorate %92 BuiltIn FragCoord
36fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
37fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
38fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
39fd4e5da5Sopenharmony_ci          %7 = OpTypeFloat 32
40fd4e5da5Sopenharmony_ci          %8 = OpTypeStruct %6 %7
41fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
42fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %6 %9
43fd4e5da5Sopenharmony_ci         %14 = OpConstant %6 0
44fd4e5da5Sopenharmony_ci         %15 = OpTypePointer Function %6
45fd4e5da5Sopenharmony_ci         %51 = OpTypePointer Private %6
46fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 2
47fd4e5da5Sopenharmony_ci         %23 = OpConstant %6 1
48fd4e5da5Sopenharmony_ci         %24 = OpConstant %7 1
49fd4e5da5Sopenharmony_ci         %25 = OpTypePointer Function %7
50fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Private %7
51fd4e5da5Sopenharmony_ci         %34 = OpTypeBool
52fd4e5da5Sopenharmony_ci         %35 = OpConstantFalse %34
53fd4e5da5Sopenharmony_ci         %60 = OpConstantNull %50
54fd4e5da5Sopenharmony_ci         %52 = OpVariable %50 Private
55fd4e5da5Sopenharmony_ci         %53 = OpVariable %51 Private
56fd4e5da5Sopenharmony_ci         %80 = OpConstantComposite %8 %21 %24
57fd4e5da5Sopenharmony_ci         %90 = OpTypeVector %7 4
58fd4e5da5Sopenharmony_ci         %91 = OpTypePointer Input %90
59fd4e5da5Sopenharmony_ci         %92 = OpVariable %91 Input
60fd4e5da5Sopenharmony_ci         %93 = OpConstantComposite %90 %24 %24 %24 %24
61fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
62fd4e5da5Sopenharmony_ci          %5 = OpLabel
63fd4e5da5Sopenharmony_ci         %20 = OpVariable %9 Function
64fd4e5da5Sopenharmony_ci         %27 = OpVariable %9 Function ; irrelevant
65fd4e5da5Sopenharmony_ci         %22 = OpAccessChain %15 %20 %14
66fd4e5da5Sopenharmony_ci         %44 = OpCopyObject %9 %20
67fd4e5da5Sopenharmony_ci         %26 = OpAccessChain %25 %20 %23
68fd4e5da5Sopenharmony_ci         %29 = OpFunctionCall %6 %12 %27
69fd4e5da5Sopenharmony_ci         %30 = OpAccessChain %15 %20 %14
70fd4e5da5Sopenharmony_ci         %45 = OpCopyObject %15 %30
71fd4e5da5Sopenharmony_ci         %81 = OpCopyObject %9 %27 ; irrelevant
72fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %15 %20 %14
73fd4e5da5Sopenharmony_ci               OpSelectionMerge %37 None
74fd4e5da5Sopenharmony_ci               OpBranchConditional %35 %36 %37
75fd4e5da5Sopenharmony_ci         %36 = OpLabel
76fd4e5da5Sopenharmony_ci         %38 = OpAccessChain %15 %20 %14
77fd4e5da5Sopenharmony_ci         %40 = OpAccessChain %15 %20 %14
78fd4e5da5Sopenharmony_ci         %43 = OpAccessChain %15 %20 %14
79fd4e5da5Sopenharmony_ci         %82 = OpCopyObject %9 %27 ; irrelevant
80fd4e5da5Sopenharmony_ci               OpBranch %37
81fd4e5da5Sopenharmony_ci         %37 = OpLabel
82fd4e5da5Sopenharmony_ci               OpReturn
83fd4e5da5Sopenharmony_ci               OpFunctionEnd
84fd4e5da5Sopenharmony_ci         %12 = OpFunction %6 None %10
85fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9 ; irrelevant
86fd4e5da5Sopenharmony_ci         %13 = OpLabel
87fd4e5da5Sopenharmony_ci         %46 = OpCopyObject %9 %11 ; irrelevant
88fd4e5da5Sopenharmony_ci         %16 = OpAccessChain %15 %11 %14 ; irrelevant
89fd4e5da5Sopenharmony_ci         %95 = OpCopyObject %8 %80
90fd4e5da5Sopenharmony_ci               OpReturnValue %21
91fd4e5da5Sopenharmony_ci               OpFunctionEnd
92fd4e5da5Sopenharmony_ci  )";
93fd4e5da5Sopenharmony_ci
94fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_4;
95fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
96fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
97fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
98fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
99fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
100fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
101fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
102fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
103fd4e5da5Sopenharmony_ci      27);
104fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
105fd4e5da5Sopenharmony_ci      11);
106fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
107fd4e5da5Sopenharmony_ci      46);
108fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
109fd4e5da5Sopenharmony_ci      16);
110fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
111fd4e5da5Sopenharmony_ci      52);
112fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
113fd4e5da5Sopenharmony_ci      81);
114fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
115fd4e5da5Sopenharmony_ci      82);
116fd4e5da5Sopenharmony_ci
117fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactBlockIsDead(36);
118fd4e5da5Sopenharmony_ci
119fd4e5da5Sopenharmony_ci  // Variables with pointee types:
120fd4e5da5Sopenharmony_ci  //  52 - ptr_to(7)
121fd4e5da5Sopenharmony_ci  //  53 - ptr_to(6)
122fd4e5da5Sopenharmony_ci  //  20 - ptr_to(8)
123fd4e5da5Sopenharmony_ci  //  27 - ptr_to(8) - irrelevant
124fd4e5da5Sopenharmony_ci  //  92 - ptr_to(90) - read only
125fd4e5da5Sopenharmony_ci
126fd4e5da5Sopenharmony_ci  // Access chains with pointee type:
127fd4e5da5Sopenharmony_ci  //  22 - ptr_to(6)
128fd4e5da5Sopenharmony_ci  //  26 - ptr_to(6)
129fd4e5da5Sopenharmony_ci  //  30 - ptr_to(6)
130fd4e5da5Sopenharmony_ci  //  33 - ptr_to(6)
131fd4e5da5Sopenharmony_ci  //  38 - ptr_to(6)
132fd4e5da5Sopenharmony_ci  //  40 - ptr_to(6)
133fd4e5da5Sopenharmony_ci  //  43 - ptr_to(6)
134fd4e5da5Sopenharmony_ci  //  16 - ptr_to(6) - irrelevant
135fd4e5da5Sopenharmony_ci
136fd4e5da5Sopenharmony_ci  // Copied object with pointee type:
137fd4e5da5Sopenharmony_ci  //  44 - ptr_to(8)
138fd4e5da5Sopenharmony_ci  //  45 - ptr_to(6)
139fd4e5da5Sopenharmony_ci  //  46 - ptr_to(8) - irrelevant
140fd4e5da5Sopenharmony_ci  //  81 - ptr_to(8) - irrelevant
141fd4e5da5Sopenharmony_ci  //  82 - ptr_to(8) - irrelevant
142fd4e5da5Sopenharmony_ci
143fd4e5da5Sopenharmony_ci  // Function parameters with pointee type:
144fd4e5da5Sopenharmony_ci  //  11 - ptr_to(8) - irrelevant
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  // Pointers that cannot be used:
147fd4e5da5Sopenharmony_ci  //  60 - null
148fd4e5da5Sopenharmony_ci  //  61 - undefined
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci  // Bad: attempt to store to 11 from outside its function
151fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
152fd4e5da5Sopenharmony_ci                   11, false, 0, 0, 80,
153fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
154fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
155fd4e5da5Sopenharmony_ci
156fd4e5da5Sopenharmony_ci  // Bad: pointer is not available
157fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
158fd4e5da5Sopenharmony_ci                   81, false, 0, 0, 80,
159fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
160fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
161fd4e5da5Sopenharmony_ci
162fd4e5da5Sopenharmony_ci  // Bad: attempt to insert before OpVariable
163fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
164fd4e5da5Sopenharmony_ci      TransformationStore(52, false, 0, 0, 24,
165fd4e5da5Sopenharmony_ci                          MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
166fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
167fd4e5da5Sopenharmony_ci
168fd4e5da5Sopenharmony_ci  // Bad: pointer id does not exist
169fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
170fd4e5da5Sopenharmony_ci                   1000, false, 0, 0, 24,
171fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
172fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
173fd4e5da5Sopenharmony_ci
174fd4e5da5Sopenharmony_ci  // Bad: pointer id exists but does not have a type
175fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
176fd4e5da5Sopenharmony_ci                   5, false, 0, 0, 24,
177fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
178fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
179fd4e5da5Sopenharmony_ci
180fd4e5da5Sopenharmony_ci  // Bad: pointer id exists and has a type, but is not a pointer
181fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
182fd4e5da5Sopenharmony_ci                   24, false, 0, 0, 24,
183fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
184fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
185fd4e5da5Sopenharmony_ci
186fd4e5da5Sopenharmony_ci  // Bad: attempt to store to a null pointer
187fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
188fd4e5da5Sopenharmony_ci                   60, false, 0, 0, 24,
189fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
190fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
191fd4e5da5Sopenharmony_ci
192fd4e5da5Sopenharmony_ci  // Bad: attempt to store to an undefined pointer
193fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
194fd4e5da5Sopenharmony_ci                   61, false, 0, 0, 21,
195fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
196fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ci  // Bad: %82 is not available at the program point
199fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
200fd4e5da5Sopenharmony_ci      TransformationStore(82, false, 0, 0, 80,
201fd4e5da5Sopenharmony_ci                          MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
202fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
203fd4e5da5Sopenharmony_ci
204fd4e5da5Sopenharmony_ci  // Bad: value id does not exist
205fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
206fd4e5da5Sopenharmony_ci                   27, false, 0, 0, 1000,
207fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
208fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ci  // Bad: value id exists but does not have a type
211fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
212fd4e5da5Sopenharmony_ci                   27, false, 0, 0, 15,
213fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
214fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
215fd4e5da5Sopenharmony_ci
216fd4e5da5Sopenharmony_ci  // Bad: value id exists but has the wrong type
217fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
218fd4e5da5Sopenharmony_ci                   27, false, 0, 0, 14,
219fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
220fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
221fd4e5da5Sopenharmony_ci
222fd4e5da5Sopenharmony_ci  // Bad: attempt to store to read-only variable
223fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
224fd4e5da5Sopenharmony_ci                   92, false, 0, 0, 93,
225fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
226fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci  // Bad: value is not available
229fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
230fd4e5da5Sopenharmony_ci                   27, false, 0, 0, 95,
231fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
232fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
233fd4e5da5Sopenharmony_ci
234fd4e5da5Sopenharmony_ci  // Bad: variable being stored to does not have an irrelevant pointee value,
235fd4e5da5Sopenharmony_ci  // and the store is not in a dead block.
236fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
237fd4e5da5Sopenharmony_ci                   20, false, 0, 0, 95,
238fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
239fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
240fd4e5da5Sopenharmony_ci
241fd4e5da5Sopenharmony_ci  // The described instruction does not exist.
242fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
243fd4e5da5Sopenharmony_ci                   27, false, 0, 0, 80,
244fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(1000, spv::Op::OpAccessChain, 0))
245fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
246fd4e5da5Sopenharmony_ci
247fd4e5da5Sopenharmony_ci  {
248fd4e5da5Sopenharmony_ci    // Store to irrelevant variable from dead block.
249fd4e5da5Sopenharmony_ci    TransformationStore transformation(
250fd4e5da5Sopenharmony_ci        27, false, 0, 0, 80,
251fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
252fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
253fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
254fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
255fd4e5da5Sopenharmony_ci                          &transformation_context);
256fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
257fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
258fd4e5da5Sopenharmony_ci  }
259fd4e5da5Sopenharmony_ci
260fd4e5da5Sopenharmony_ci  {
261fd4e5da5Sopenharmony_ci    // Store to irrelevant variable from live block.
262fd4e5da5Sopenharmony_ci    TransformationStore transformation(
263fd4e5da5Sopenharmony_ci        11, false, 0, 0, 95,
264fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
265fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
266fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
267fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
268fd4e5da5Sopenharmony_ci                          &transformation_context);
269fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
270fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
271fd4e5da5Sopenharmony_ci  }
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ci  {
274fd4e5da5Sopenharmony_ci    // Store to irrelevant variable from live block.
275fd4e5da5Sopenharmony_ci    TransformationStore transformation(
276fd4e5da5Sopenharmony_ci        46, false, 0, 0, 80,
277fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
278fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
279fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
280fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
281fd4e5da5Sopenharmony_ci                          &transformation_context);
282fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
283fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
284fd4e5da5Sopenharmony_ci  }
285fd4e5da5Sopenharmony_ci
286fd4e5da5Sopenharmony_ci  {
287fd4e5da5Sopenharmony_ci    // Store to irrelevant variable from live block.
288fd4e5da5Sopenharmony_ci    TransformationStore transformation(
289fd4e5da5Sopenharmony_ci        16, false, 0, 0, 21,
290fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
291fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
292fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
293fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
294fd4e5da5Sopenharmony_ci                          &transformation_context);
295fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
296fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
297fd4e5da5Sopenharmony_ci  }
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ci  {
300fd4e5da5Sopenharmony_ci    // Store to non-irrelevant variable from dead block.
301fd4e5da5Sopenharmony_ci    TransformationStore transformation(
302fd4e5da5Sopenharmony_ci        53, false, 0, 0, 21,
303fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
304fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
305fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
306fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
307fd4e5da5Sopenharmony_ci                          &transformation_context);
308fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
309fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
310fd4e5da5Sopenharmony_ci  }
311fd4e5da5Sopenharmony_ci
312fd4e5da5Sopenharmony_ci  std::string after_transformation = R"(
313fd4e5da5Sopenharmony_ci               OpCapability Shader
314fd4e5da5Sopenharmony_ci               OpCapability VariablePointers
315fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
316fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
317fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main" %92 %52 %53
318fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
319fd4e5da5Sopenharmony_ci               OpSource ESSL 310
320fd4e5da5Sopenharmony_ci               OpDecorate %92 BuiltIn FragCoord
321fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
322fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
323fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
324fd4e5da5Sopenharmony_ci          %7 = OpTypeFloat 32
325fd4e5da5Sopenharmony_ci          %8 = OpTypeStruct %6 %7
326fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
327fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %6 %9
328fd4e5da5Sopenharmony_ci         %14 = OpConstant %6 0
329fd4e5da5Sopenharmony_ci         %15 = OpTypePointer Function %6
330fd4e5da5Sopenharmony_ci         %51 = OpTypePointer Private %6
331fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 2
332fd4e5da5Sopenharmony_ci         %23 = OpConstant %6 1
333fd4e5da5Sopenharmony_ci         %24 = OpConstant %7 1
334fd4e5da5Sopenharmony_ci         %25 = OpTypePointer Function %7
335fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Private %7
336fd4e5da5Sopenharmony_ci         %34 = OpTypeBool
337fd4e5da5Sopenharmony_ci         %35 = OpConstantFalse %34
338fd4e5da5Sopenharmony_ci         %60 = OpConstantNull %50
339fd4e5da5Sopenharmony_ci         %52 = OpVariable %50 Private
340fd4e5da5Sopenharmony_ci         %53 = OpVariable %51 Private
341fd4e5da5Sopenharmony_ci         %80 = OpConstantComposite %8 %21 %24
342fd4e5da5Sopenharmony_ci         %90 = OpTypeVector %7 4
343fd4e5da5Sopenharmony_ci         %91 = OpTypePointer Input %90
344fd4e5da5Sopenharmony_ci         %92 = OpVariable %91 Input
345fd4e5da5Sopenharmony_ci         %93 = OpConstantComposite %90 %24 %24 %24 %24
346fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
347fd4e5da5Sopenharmony_ci          %5 = OpLabel
348fd4e5da5Sopenharmony_ci         %20 = OpVariable %9 Function
349fd4e5da5Sopenharmony_ci         %27 = OpVariable %9 Function ; irrelevant
350fd4e5da5Sopenharmony_ci         %22 = OpAccessChain %15 %20 %14
351fd4e5da5Sopenharmony_ci         %44 = OpCopyObject %9 %20
352fd4e5da5Sopenharmony_ci         %26 = OpAccessChain %25 %20 %23
353fd4e5da5Sopenharmony_ci         %29 = OpFunctionCall %6 %12 %27
354fd4e5da5Sopenharmony_ci         %30 = OpAccessChain %15 %20 %14
355fd4e5da5Sopenharmony_ci         %45 = OpCopyObject %15 %30
356fd4e5da5Sopenharmony_ci         %81 = OpCopyObject %9 %27 ; irrelevant
357fd4e5da5Sopenharmony_ci         %33 = OpAccessChain %15 %20 %14
358fd4e5da5Sopenharmony_ci               OpSelectionMerge %37 None
359fd4e5da5Sopenharmony_ci               OpBranchConditional %35 %36 %37
360fd4e5da5Sopenharmony_ci         %36 = OpLabel
361fd4e5da5Sopenharmony_ci               OpStore %27 %80
362fd4e5da5Sopenharmony_ci               OpStore %53 %21
363fd4e5da5Sopenharmony_ci         %38 = OpAccessChain %15 %20 %14
364fd4e5da5Sopenharmony_ci         %40 = OpAccessChain %15 %20 %14
365fd4e5da5Sopenharmony_ci         %43 = OpAccessChain %15 %20 %14
366fd4e5da5Sopenharmony_ci         %82 = OpCopyObject %9 %27 ; irrelevant
367fd4e5da5Sopenharmony_ci               OpBranch %37
368fd4e5da5Sopenharmony_ci         %37 = OpLabel
369fd4e5da5Sopenharmony_ci               OpReturn
370fd4e5da5Sopenharmony_ci               OpFunctionEnd
371fd4e5da5Sopenharmony_ci         %12 = OpFunction %6 None %10
372fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %9 ; irrelevant
373fd4e5da5Sopenharmony_ci         %13 = OpLabel
374fd4e5da5Sopenharmony_ci         %46 = OpCopyObject %9 %11 ; irrelevant
375fd4e5da5Sopenharmony_ci         %16 = OpAccessChain %15 %11 %14 ; irrelevant
376fd4e5da5Sopenharmony_ci         %95 = OpCopyObject %8 %80
377fd4e5da5Sopenharmony_ci               OpStore %11 %95
378fd4e5da5Sopenharmony_ci               OpStore %46 %80
379fd4e5da5Sopenharmony_ci               OpStore %16 %21
380fd4e5da5Sopenharmony_ci               OpReturnValue %21
381fd4e5da5Sopenharmony_ci               OpFunctionEnd
382fd4e5da5Sopenharmony_ci  )";
383fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
384fd4e5da5Sopenharmony_ci}
385fd4e5da5Sopenharmony_ci
386fd4e5da5Sopenharmony_ciTEST(TransformationStoreTest, DoNotAllowStoresToReadOnlyMemory) {
387fd4e5da5Sopenharmony_ci  std::string shader = R"(
388fd4e5da5Sopenharmony_ci               OpCapability Shader
389fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
390fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
391fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
392fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
393fd4e5da5Sopenharmony_ci               OpSource ESSL 320
394fd4e5da5Sopenharmony_ci               OpMemberDecorate %10 0 Offset 0
395fd4e5da5Sopenharmony_ci               OpMemberDecorate %10 1 Offset 4
396fd4e5da5Sopenharmony_ci               OpDecorate %10 Block
397fd4e5da5Sopenharmony_ci               OpMemberDecorate %23 0 Offset 0
398fd4e5da5Sopenharmony_ci               OpDecorate %23 Block
399fd4e5da5Sopenharmony_ci               OpDecorate %25 DescriptorSet 0
400fd4e5da5Sopenharmony_ci               OpDecorate %25 Binding 0
401fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
402fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
403fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
404fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
405fd4e5da5Sopenharmony_ci          %9 = OpTypeFloat 32
406fd4e5da5Sopenharmony_ci         %10 = OpTypeStruct %6 %9
407fd4e5da5Sopenharmony_ci         %11 = OpTypePointer PushConstant %10
408fd4e5da5Sopenharmony_ci         %12 = OpVariable %11 PushConstant
409fd4e5da5Sopenharmony_ci         %13 = OpConstant %6 0
410fd4e5da5Sopenharmony_ci         %14 = OpTypePointer PushConstant %6
411fd4e5da5Sopenharmony_ci         %17 = OpConstant %6 1
412fd4e5da5Sopenharmony_ci         %18 = OpTypePointer PushConstant %9
413fd4e5da5Sopenharmony_ci         %23 = OpTypeStruct %9
414fd4e5da5Sopenharmony_ci         %24 = OpTypePointer UniformConstant %23
415fd4e5da5Sopenharmony_ci         %25 = OpVariable %24 UniformConstant
416fd4e5da5Sopenharmony_ci         %26 = OpTypePointer UniformConstant %9
417fd4e5da5Sopenharmony_ci         %50 = OpConstant %9 0
418fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
419fd4e5da5Sopenharmony_ci          %5 = OpLabel
420fd4e5da5Sopenharmony_ci         %15 = OpAccessChain %14 %12 %13
421fd4e5da5Sopenharmony_ci         %19 = OpAccessChain %18 %12 %17
422fd4e5da5Sopenharmony_ci         %27 = OpAccessChain %26 %25 %13
423fd4e5da5Sopenharmony_ci               OpReturn
424fd4e5da5Sopenharmony_ci               OpFunctionEnd
425fd4e5da5Sopenharmony_ci  )";
426fd4e5da5Sopenharmony_ci
427fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
428fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
429fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
430fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
431fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
432fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
433fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
434fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
435fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactBlockIsDead(5);
436fd4e5da5Sopenharmony_ci
437fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
438fd4e5da5Sopenharmony_ci      TransformationStore(15, false, 0, 0, 13,
439fd4e5da5Sopenharmony_ci                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
440fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
441fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
442fd4e5da5Sopenharmony_ci      TransformationStore(19, false, 0, 0, 50,
443fd4e5da5Sopenharmony_ci                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
444fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
445fd4e5da5Sopenharmony_ci  ASSERT_FALSE(
446fd4e5da5Sopenharmony_ci      TransformationStore(27, false, 0, 0, 50,
447fd4e5da5Sopenharmony_ci                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
448fd4e5da5Sopenharmony_ci          .IsApplicable(context.get(), transformation_context));
449fd4e5da5Sopenharmony_ci}
450fd4e5da5Sopenharmony_ci
451fd4e5da5Sopenharmony_ciTEST(TransformationStoreTest, SupportAtomicStore) {
452fd4e5da5Sopenharmony_ci  const std::string shader = R"(
453fd4e5da5Sopenharmony_ci               OpCapability Shader
454fd4e5da5Sopenharmony_ci               OpCapability Int8
455fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
456fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
457fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
458fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
459fd4e5da5Sopenharmony_ci               OpSource ESSL 320
460fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
461fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
462fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
463fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 8 1
464fd4e5da5Sopenharmony_ci          %9 = OpTypeInt 32 0
465fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
466fd4e5da5Sopenharmony_ci          %8 = OpTypeStruct %6
467fd4e5da5Sopenharmony_ci         %10 = OpTypePointer StorageBuffer %8
468fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 StorageBuffer
469fd4e5da5Sopenharmony_ci         %19 = OpConstant %26 0
470fd4e5da5Sopenharmony_ci         %18 = OpConstant %9 1
471fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 0
472fd4e5da5Sopenharmony_ci         %13 = OpTypePointer StorageBuffer %6
473fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 4
474fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 7
475fd4e5da5Sopenharmony_ci         %17 = OpConstant %7 4
476fd4e5da5Sopenharmony_ci         %20 = OpConstant %9 64
477fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 15
478fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
479fd4e5da5Sopenharmony_ci          %5 = OpLabel
480fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %13 %11 %12
481fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %13 %11 %12
482fd4e5da5Sopenharmony_ci               OpReturn
483fd4e5da5Sopenharmony_ci               OpFunctionEnd
484fd4e5da5Sopenharmony_ci  )";
485fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
486fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
487fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
488fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
489fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
490fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
491fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
492fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
493fd4e5da5Sopenharmony_ci
494fd4e5da5Sopenharmony_ci  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
495fd4e5da5Sopenharmony_ci      14);
496fd4e5da5Sopenharmony_ci
497fd4e5da5Sopenharmony_ci  // Bad: id 100 of memory scope instruction does not exist.
498fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
499fd4e5da5Sopenharmony_ci                   14, true, 100, 20, 21,
500fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
501fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
502fd4e5da5Sopenharmony_ci  // Bad: id 100 of memory semantics instruction does not exist.
503fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
504fd4e5da5Sopenharmony_ci                   14, true, 15, 100, 21,
505fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
506fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
507fd4e5da5Sopenharmony_ci  // Bad: memory scope should be |OpConstant| opcode.
508fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
509fd4e5da5Sopenharmony_ci                   14, true, 5, 20, 21,
510fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
511fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
512fd4e5da5Sopenharmony_ci  // Bad: memory semantics should be |OpConstant| opcode.
513fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
514fd4e5da5Sopenharmony_ci                   14, true, 15, 5, 21,
515fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
516fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
517fd4e5da5Sopenharmony_ci
518fd4e5da5Sopenharmony_ci  // Bad: The memory scope instruction must have an Integer operand.
519fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
520fd4e5da5Sopenharmony_ci                   14, true, 15, 19, 21,
521fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
522fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
523fd4e5da5Sopenharmony_ci  // Bad: The memory memory semantics instruction must have an Integer operand.
524fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
525fd4e5da5Sopenharmony_ci                   14, true, 19, 20, 21,
526fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
527fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
528fd4e5da5Sopenharmony_ci
529fd4e5da5Sopenharmony_ci  // Bad: Integer size of the memory scope must be equal to 32 bits.
530fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
531fd4e5da5Sopenharmony_ci                   14, true, 17, 20, 21,
532fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
533fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
534fd4e5da5Sopenharmony_ci
535fd4e5da5Sopenharmony_ci  // Bad: Integer size of memory semantics must be equal to 32 bits.
536fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
537fd4e5da5Sopenharmony_ci                   14, true, 15, 17, 21,
538fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
539fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
540fd4e5da5Sopenharmony_ci
541fd4e5da5Sopenharmony_ci  // Bad: memory scope value must be 4 (spv::Scope::Invocation).
542fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
543fd4e5da5Sopenharmony_ci                   14, true, 16, 20, 21,
544fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
545fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
546fd4e5da5Sopenharmony_ci
547fd4e5da5Sopenharmony_ci  // Bad: memory semantics value must be either:
548fd4e5da5Sopenharmony_ci  // 64 (SpvMemorySemanticsUniformMemoryMask)
549fd4e5da5Sopenharmony_ci  // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
550fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
551fd4e5da5Sopenharmony_ci                   14, true, 15, 16, 21,
552fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
553fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
554fd4e5da5Sopenharmony_ci  // Bad: The described instruction does not exist
555fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
556fd4e5da5Sopenharmony_ci                   14, true, 15, 20, 21,
557fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
558fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
559fd4e5da5Sopenharmony_ci
560fd4e5da5Sopenharmony_ci  // Bad: Can't insert OpAccessChain before the id 15 of memory scope.
561fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
562fd4e5da5Sopenharmony_ci                   14, true, 15, 20, 21,
563fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(15, spv::Op::OpAccessChain, 0))
564fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
565fd4e5da5Sopenharmony_ci
566fd4e5da5Sopenharmony_ci  // Bad: Can't insert OpAccessChain before the id 20 of memory semantics.
567fd4e5da5Sopenharmony_ci  ASSERT_FALSE(TransformationStore(
568fd4e5da5Sopenharmony_ci                   14, true, 15, 20, 21,
569fd4e5da5Sopenharmony_ci                   MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0))
570fd4e5da5Sopenharmony_ci                   .IsApplicable(context.get(), transformation_context));
571fd4e5da5Sopenharmony_ci
572fd4e5da5Sopenharmony_ci  // Successful transformations.
573fd4e5da5Sopenharmony_ci  {
574fd4e5da5Sopenharmony_ci    TransformationStore transformation(
575fd4e5da5Sopenharmony_ci        14, true, 15, 20, 21,
576fd4e5da5Sopenharmony_ci        MakeInstructionDescriptor(24, spv::Op::OpReturn, 0));
577fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
578fd4e5da5Sopenharmony_ci        transformation.IsApplicable(context.get(), transformation_context));
579fd4e5da5Sopenharmony_ci    ApplyAndCheckFreshIds(transformation, context.get(),
580fd4e5da5Sopenharmony_ci                          &transformation_context);
581fd4e5da5Sopenharmony_ci    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
582fd4e5da5Sopenharmony_ci        context.get(), validator_options, kConsoleMessageConsumer));
583fd4e5da5Sopenharmony_ci  }
584fd4e5da5Sopenharmony_ci
585fd4e5da5Sopenharmony_ci  const std::string after_transformation = R"(
586fd4e5da5Sopenharmony_ci               OpCapability Shader
587fd4e5da5Sopenharmony_ci               OpCapability Int8
588fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
589fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
590fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
591fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
592fd4e5da5Sopenharmony_ci               OpSource ESSL 320
593fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
594fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
595fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
596fd4e5da5Sopenharmony_ci          %7 = OpTypeInt 8 1
597fd4e5da5Sopenharmony_ci          %9 = OpTypeInt 32 0
598fd4e5da5Sopenharmony_ci         %26 = OpTypeFloat 32
599fd4e5da5Sopenharmony_ci          %8 = OpTypeStruct %6
600fd4e5da5Sopenharmony_ci         %10 = OpTypePointer StorageBuffer %8
601fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 StorageBuffer
602fd4e5da5Sopenharmony_ci         %19 = OpConstant %26 0
603fd4e5da5Sopenharmony_ci         %18 = OpConstant %9 1
604fd4e5da5Sopenharmony_ci         %12 = OpConstant %6 0
605fd4e5da5Sopenharmony_ci         %13 = OpTypePointer StorageBuffer %6
606fd4e5da5Sopenharmony_ci         %15 = OpConstant %6 4
607fd4e5da5Sopenharmony_ci         %16 = OpConstant %6 7
608fd4e5da5Sopenharmony_ci         %17 = OpConstant %7 4
609fd4e5da5Sopenharmony_ci         %20 = OpConstant %9 64
610fd4e5da5Sopenharmony_ci         %21 = OpConstant %6 15
611fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
612fd4e5da5Sopenharmony_ci          %5 = OpLabel
613fd4e5da5Sopenharmony_ci         %14 = OpAccessChain %13 %11 %12
614fd4e5da5Sopenharmony_ci         %24 = OpAccessChain %13 %11 %12
615fd4e5da5Sopenharmony_ci               OpAtomicStore %14 %15 %20 %21
616fd4e5da5Sopenharmony_ci               OpReturn
617fd4e5da5Sopenharmony_ci               OpFunctionEnd
618fd4e5da5Sopenharmony_ci  )";
619fd4e5da5Sopenharmony_ci
620fd4e5da5Sopenharmony_ci  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
621fd4e5da5Sopenharmony_ci}
622fd4e5da5Sopenharmony_ci
623fd4e5da5Sopenharmony_ci}  // namespace
624fd4e5da5Sopenharmony_ci}  // namespace fuzz
625fd4e5da5Sopenharmony_ci}  // namespace spvtools
626