1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 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/replayer.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/data_descriptor.h"
19fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
20fd4e5da5Sopenharmony_ci#include "source/fuzz/instruction_descriptor.h"
21fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_add_constant_scalar.h"
22fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_add_global_variable.h"
23fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_add_parameter.h"
24fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_add_synonym.h"
25fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_flatten_conditional_branch.h"
26fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_split_block.h"
27fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_cinamespace spvtools {
30fd4e5da5Sopenharmony_cinamespace fuzz {
31fd4e5da5Sopenharmony_cinamespace {
32fd4e5da5Sopenharmony_ci
33fd4e5da5Sopenharmony_ciTEST(ReplayerTest, PartialReplay) {
34fd4e5da5Sopenharmony_ci  const std::string kTestShader = R"(
35fd4e5da5Sopenharmony_ci               OpCapability Shader
36fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
37fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
38fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
39fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
40fd4e5da5Sopenharmony_ci               OpSource ESSL 310
41fd4e5da5Sopenharmony_ci               OpName %4 "main"
42fd4e5da5Sopenharmony_ci               OpName %8 "g"
43fd4e5da5Sopenharmony_ci               OpName %11 "x"
44fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
45fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
46fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
47fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Private %6
48fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Private
49fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 10
50fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Function %6
51fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
52fd4e5da5Sopenharmony_ci          %5 = OpLabel
53fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 Function
54fd4e5da5Sopenharmony_ci               OpStore %8 %9
55fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %8
56fd4e5da5Sopenharmony_ci               OpStore %11 %12
57fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %8
58fd4e5da5Sopenharmony_ci               OpStore %11 %13
59fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %8
60fd4e5da5Sopenharmony_ci               OpStore %11 %14
61fd4e5da5Sopenharmony_ci         %15 = OpLoad %6 %8
62fd4e5da5Sopenharmony_ci               OpStore %11 %15
63fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %8
64fd4e5da5Sopenharmony_ci               OpStore %11 %16
65fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %8
66fd4e5da5Sopenharmony_ci               OpStore %11 %17
67fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %8
68fd4e5da5Sopenharmony_ci               OpStore %11 %18
69fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %8
70fd4e5da5Sopenharmony_ci               OpStore %11 %19
71fd4e5da5Sopenharmony_ci         %20 = OpLoad %6 %8
72fd4e5da5Sopenharmony_ci               OpStore %11 %20
73fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
74fd4e5da5Sopenharmony_ci               OpStore %11 %21
75fd4e5da5Sopenharmony_ci         %22 = OpLoad %6 %8
76fd4e5da5Sopenharmony_ci               OpStore %11 %22
77fd4e5da5Sopenharmony_ci               OpReturn
78fd4e5da5Sopenharmony_ci               OpFunctionEnd
79fd4e5da5Sopenharmony_ci  )";
80fd4e5da5Sopenharmony_ci
81fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
82fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
83fd4e5da5Sopenharmony_ci
84fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_in;
85fd4e5da5Sopenharmony_ci  SpirvTools t(env);
86fd4e5da5Sopenharmony_ci  t.SetMessageConsumer(kConsoleMessageConsumer);
87fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Assemble(kTestShader, &binary_in, kFuzzAssembleOption));
88fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Validate(binary_in));
89fd4e5da5Sopenharmony_ci
90fd4e5da5Sopenharmony_ci  protobufs::TransformationSequence transformations;
91fd4e5da5Sopenharmony_ci  for (uint32_t id = 12; id <= 22; id++) {
92fd4e5da5Sopenharmony_ci    *transformations.add_transformation() =
93fd4e5da5Sopenharmony_ci        TransformationSplitBlock(
94fd4e5da5Sopenharmony_ci            MakeInstructionDescriptor(id, spv::Op::OpLoad, 0), id + 100)
95fd4e5da5Sopenharmony_ci            .ToMessage();
96fd4e5da5Sopenharmony_ci  }
97fd4e5da5Sopenharmony_ci
98fd4e5da5Sopenharmony_ci  {
99fd4e5da5Sopenharmony_ci    // Full replay
100fd4e5da5Sopenharmony_ci    protobufs::FactSequence empty_facts;
101fd4e5da5Sopenharmony_ci    auto replayer_result =
102fd4e5da5Sopenharmony_ci        Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
103fd4e5da5Sopenharmony_ci                 transformations, 11, true, validator_options)
104fd4e5da5Sopenharmony_ci            .Run();
105fd4e5da5Sopenharmony_ci    // Replay should succeed.
106fd4e5da5Sopenharmony_ci    ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete,
107fd4e5da5Sopenharmony_ci              replayer_result.status);
108fd4e5da5Sopenharmony_ci    // All transformations should be applied.
109fd4e5da5Sopenharmony_ci    ASSERT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
110fd4e5da5Sopenharmony_ci        transformations, replayer_result.applied_transformations));
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_ci    const std::string kFullySplitShader = R"(
113fd4e5da5Sopenharmony_ci               OpCapability Shader
114fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
115fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
116fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
117fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
118fd4e5da5Sopenharmony_ci               OpSource ESSL 310
119fd4e5da5Sopenharmony_ci               OpName %4 "main"
120fd4e5da5Sopenharmony_ci               OpName %8 "g"
121fd4e5da5Sopenharmony_ci               OpName %11 "x"
122fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
123fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
124fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
125fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Private %6
126fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Private
127fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 10
128fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Function %6
129fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
130fd4e5da5Sopenharmony_ci          %5 = OpLabel
131fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 Function
132fd4e5da5Sopenharmony_ci               OpStore %8 %9
133fd4e5da5Sopenharmony_ci               OpBranch %112
134fd4e5da5Sopenharmony_ci        %112 = OpLabel
135fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %8
136fd4e5da5Sopenharmony_ci               OpStore %11 %12
137fd4e5da5Sopenharmony_ci               OpBranch %113
138fd4e5da5Sopenharmony_ci        %113 = OpLabel
139fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %8
140fd4e5da5Sopenharmony_ci               OpStore %11 %13
141fd4e5da5Sopenharmony_ci               OpBranch %114
142fd4e5da5Sopenharmony_ci        %114 = OpLabel
143fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %8
144fd4e5da5Sopenharmony_ci               OpStore %11 %14
145fd4e5da5Sopenharmony_ci               OpBranch %115
146fd4e5da5Sopenharmony_ci        %115 = OpLabel
147fd4e5da5Sopenharmony_ci         %15 = OpLoad %6 %8
148fd4e5da5Sopenharmony_ci               OpStore %11 %15
149fd4e5da5Sopenharmony_ci               OpBranch %116
150fd4e5da5Sopenharmony_ci        %116 = OpLabel
151fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %8
152fd4e5da5Sopenharmony_ci               OpStore %11 %16
153fd4e5da5Sopenharmony_ci               OpBranch %117
154fd4e5da5Sopenharmony_ci        %117 = OpLabel
155fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %8
156fd4e5da5Sopenharmony_ci               OpStore %11 %17
157fd4e5da5Sopenharmony_ci               OpBranch %118
158fd4e5da5Sopenharmony_ci        %118 = OpLabel
159fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %8
160fd4e5da5Sopenharmony_ci               OpStore %11 %18
161fd4e5da5Sopenharmony_ci               OpBranch %119
162fd4e5da5Sopenharmony_ci        %119 = OpLabel
163fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %8
164fd4e5da5Sopenharmony_ci               OpStore %11 %19
165fd4e5da5Sopenharmony_ci               OpBranch %120
166fd4e5da5Sopenharmony_ci        %120 = OpLabel
167fd4e5da5Sopenharmony_ci         %20 = OpLoad %6 %8
168fd4e5da5Sopenharmony_ci               OpStore %11 %20
169fd4e5da5Sopenharmony_ci               OpBranch %121
170fd4e5da5Sopenharmony_ci        %121 = OpLabel
171fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
172fd4e5da5Sopenharmony_ci               OpStore %11 %21
173fd4e5da5Sopenharmony_ci               OpBranch %122
174fd4e5da5Sopenharmony_ci        %122 = OpLabel
175fd4e5da5Sopenharmony_ci         %22 = OpLoad %6 %8
176fd4e5da5Sopenharmony_ci               OpStore %11 %22
177fd4e5da5Sopenharmony_ci               OpReturn
178fd4e5da5Sopenharmony_ci               OpFunctionEnd
179fd4e5da5Sopenharmony_ci    )";
180fd4e5da5Sopenharmony_ci    ASSERT_TRUE(IsEqual(env, kFullySplitShader,
181fd4e5da5Sopenharmony_ci                        replayer_result.transformed_module.get()));
182fd4e5da5Sopenharmony_ci  }
183fd4e5da5Sopenharmony_ci
184fd4e5da5Sopenharmony_ci  {
185fd4e5da5Sopenharmony_ci    // Half replay
186fd4e5da5Sopenharmony_ci    protobufs::FactSequence empty_facts;
187fd4e5da5Sopenharmony_ci    auto replayer_result =
188fd4e5da5Sopenharmony_ci        Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
189fd4e5da5Sopenharmony_ci                 transformations, 5, true, validator_options)
190fd4e5da5Sopenharmony_ci            .Run();
191fd4e5da5Sopenharmony_ci    // Replay should succeed.
192fd4e5da5Sopenharmony_ci    ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete,
193fd4e5da5Sopenharmony_ci              replayer_result.status);
194fd4e5da5Sopenharmony_ci    // The first 5 transformations should be applied
195fd4e5da5Sopenharmony_ci    ASSERT_EQ(5, replayer_result.applied_transformations.transformation_size());
196fd4e5da5Sopenharmony_ci    for (uint32_t i = 0; i < 5; i++) {
197fd4e5da5Sopenharmony_ci      ASSERT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
198fd4e5da5Sopenharmony_ci          transformations.transformation(i),
199fd4e5da5Sopenharmony_ci          replayer_result.applied_transformations.transformation(i)));
200fd4e5da5Sopenharmony_ci    }
201fd4e5da5Sopenharmony_ci
202fd4e5da5Sopenharmony_ci    const std::string kHalfSplitShader = R"(
203fd4e5da5Sopenharmony_ci               OpCapability Shader
204fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
205fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
206fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
207fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
208fd4e5da5Sopenharmony_ci               OpSource ESSL 310
209fd4e5da5Sopenharmony_ci               OpName %4 "main"
210fd4e5da5Sopenharmony_ci               OpName %8 "g"
211fd4e5da5Sopenharmony_ci               OpName %11 "x"
212fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
213fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
214fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
215fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Private %6
216fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Private
217fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 10
218fd4e5da5Sopenharmony_ci         %10 = OpTypePointer Function %6
219fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
220fd4e5da5Sopenharmony_ci          %5 = OpLabel
221fd4e5da5Sopenharmony_ci         %11 = OpVariable %10 Function
222fd4e5da5Sopenharmony_ci               OpStore %8 %9
223fd4e5da5Sopenharmony_ci               OpBranch %112
224fd4e5da5Sopenharmony_ci        %112 = OpLabel
225fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %8
226fd4e5da5Sopenharmony_ci               OpStore %11 %12
227fd4e5da5Sopenharmony_ci               OpBranch %113
228fd4e5da5Sopenharmony_ci        %113 = OpLabel
229fd4e5da5Sopenharmony_ci         %13 = OpLoad %6 %8
230fd4e5da5Sopenharmony_ci               OpStore %11 %13
231fd4e5da5Sopenharmony_ci               OpBranch %114
232fd4e5da5Sopenharmony_ci        %114 = OpLabel
233fd4e5da5Sopenharmony_ci         %14 = OpLoad %6 %8
234fd4e5da5Sopenharmony_ci               OpStore %11 %14
235fd4e5da5Sopenharmony_ci               OpBranch %115
236fd4e5da5Sopenharmony_ci        %115 = OpLabel
237fd4e5da5Sopenharmony_ci         %15 = OpLoad %6 %8
238fd4e5da5Sopenharmony_ci               OpStore %11 %15
239fd4e5da5Sopenharmony_ci               OpBranch %116
240fd4e5da5Sopenharmony_ci        %116 = OpLabel
241fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %8
242fd4e5da5Sopenharmony_ci               OpStore %11 %16
243fd4e5da5Sopenharmony_ci         %17 = OpLoad %6 %8
244fd4e5da5Sopenharmony_ci               OpStore %11 %17
245fd4e5da5Sopenharmony_ci         %18 = OpLoad %6 %8
246fd4e5da5Sopenharmony_ci               OpStore %11 %18
247fd4e5da5Sopenharmony_ci         %19 = OpLoad %6 %8
248fd4e5da5Sopenharmony_ci               OpStore %11 %19
249fd4e5da5Sopenharmony_ci         %20 = OpLoad %6 %8
250fd4e5da5Sopenharmony_ci               OpStore %11 %20
251fd4e5da5Sopenharmony_ci         %21 = OpLoad %6 %8
252fd4e5da5Sopenharmony_ci               OpStore %11 %21
253fd4e5da5Sopenharmony_ci         %22 = OpLoad %6 %8
254fd4e5da5Sopenharmony_ci               OpStore %11 %22
255fd4e5da5Sopenharmony_ci               OpReturn
256fd4e5da5Sopenharmony_ci               OpFunctionEnd
257fd4e5da5Sopenharmony_ci    )";
258fd4e5da5Sopenharmony_ci    ASSERT_TRUE(IsEqual(env, kHalfSplitShader,
259fd4e5da5Sopenharmony_ci                        replayer_result.transformed_module.get()));
260fd4e5da5Sopenharmony_ci  }
261fd4e5da5Sopenharmony_ci
262fd4e5da5Sopenharmony_ci  {
263fd4e5da5Sopenharmony_ci    // Empty replay
264fd4e5da5Sopenharmony_ci    protobufs::FactSequence empty_facts;
265fd4e5da5Sopenharmony_ci    auto replayer_result =
266fd4e5da5Sopenharmony_ci        Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
267fd4e5da5Sopenharmony_ci                 transformations, 0, true, validator_options)
268fd4e5da5Sopenharmony_ci            .Run();
269fd4e5da5Sopenharmony_ci    // Replay should succeed.
270fd4e5da5Sopenharmony_ci    ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete,
271fd4e5da5Sopenharmony_ci              replayer_result.status);
272fd4e5da5Sopenharmony_ci    // No transformations should be applied
273fd4e5da5Sopenharmony_ci    ASSERT_EQ(0, replayer_result.applied_transformations.transformation_size());
274fd4e5da5Sopenharmony_ci    ASSERT_TRUE(
275fd4e5da5Sopenharmony_ci        IsEqual(env, kTestShader, replayer_result.transformed_module.get()));
276fd4e5da5Sopenharmony_ci  }
277fd4e5da5Sopenharmony_ci
278fd4e5da5Sopenharmony_ci  {
279fd4e5da5Sopenharmony_ci    // Invalid replay: too many transformations
280fd4e5da5Sopenharmony_ci    protobufs::FactSequence empty_facts;
281fd4e5da5Sopenharmony_ci    // The number of transformations requested to be applied exceeds the number
282fd4e5da5Sopenharmony_ci    // of transformations
283fd4e5da5Sopenharmony_ci    auto replayer_result =
284fd4e5da5Sopenharmony_ci        Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
285fd4e5da5Sopenharmony_ci                 transformations, 12, true, validator_options)
286fd4e5da5Sopenharmony_ci            .Run();
287fd4e5da5Sopenharmony_ci
288fd4e5da5Sopenharmony_ci    // Replay should not succeed.
289fd4e5da5Sopenharmony_ci    ASSERT_EQ(Replayer::ReplayerResultStatus::kTooManyTransformationsRequested,
290fd4e5da5Sopenharmony_ci              replayer_result.status);
291fd4e5da5Sopenharmony_ci    // No transformations should be applied
292fd4e5da5Sopenharmony_ci    ASSERT_EQ(0, replayer_result.applied_transformations.transformation_size());
293fd4e5da5Sopenharmony_ci    // The output binary should be empty
294fd4e5da5Sopenharmony_ci    ASSERT_EQ(nullptr, replayer_result.transformed_module);
295fd4e5da5Sopenharmony_ci  }
296fd4e5da5Sopenharmony_ci}
297fd4e5da5Sopenharmony_ci
298fd4e5da5Sopenharmony_ciTEST(ReplayerTest, CheckFactsAfterReplay) {
299fd4e5da5Sopenharmony_ci  const std::string kTestShader = R"(
300fd4e5da5Sopenharmony_ci               OpCapability Shader
301fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
302fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
303fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
304fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
305fd4e5da5Sopenharmony_ci               OpSource ESSL 320
306fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
307fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
308fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
309fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
310fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Private %8
311fd4e5da5Sopenharmony_ci         %11 = OpConstant %8 1
312fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
313fd4e5da5Sopenharmony_ci          %5 = OpLabel
314fd4e5da5Sopenharmony_ci         %10 = OpVariable %9 Function
315fd4e5da5Sopenharmony_ci               OpStore %10 %11
316fd4e5da5Sopenharmony_ci         %12 = OpFunctionCall %2 %6
317fd4e5da5Sopenharmony_ci               OpReturn
318fd4e5da5Sopenharmony_ci               OpFunctionEnd
319fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
320fd4e5da5Sopenharmony_ci          %7 = OpLabel
321fd4e5da5Sopenharmony_ci               OpReturn
322fd4e5da5Sopenharmony_ci               OpFunctionEnd
323fd4e5da5Sopenharmony_ci  )";
324fd4e5da5Sopenharmony_ci
325fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
326fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
327fd4e5da5Sopenharmony_ci
328fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_in;
329fd4e5da5Sopenharmony_ci  SpirvTools t(env);
330fd4e5da5Sopenharmony_ci  t.SetMessageConsumer(kConsoleMessageConsumer);
331fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Assemble(kTestShader, &binary_in, kFuzzAssembleOption));
332fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Validate(binary_in));
333fd4e5da5Sopenharmony_ci
334fd4e5da5Sopenharmony_ci  protobufs::TransformationSequence transformations;
335fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
336fd4e5da5Sopenharmony_ci      TransformationAddConstantScalar(100, 8, {42}, true).ToMessage();
337fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
338fd4e5da5Sopenharmony_ci      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 100,
339fd4e5da5Sopenharmony_ci                                      true)
340fd4e5da5Sopenharmony_ci          .ToMessage();
341fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
342fd4e5da5Sopenharmony_ci      TransformationAddParameter(6, 102, 8, {{12, 100}}, 103).ToMessage();
343fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
344fd4e5da5Sopenharmony_ci      TransformationAddSynonym(
345fd4e5da5Sopenharmony_ci          11,
346fd4e5da5Sopenharmony_ci          protobufs::TransformationAddSynonym::SynonymType::
347fd4e5da5Sopenharmony_ci              TransformationAddSynonym_SynonymType_COPY_OBJECT,
348fd4e5da5Sopenharmony_ci          104, MakeInstructionDescriptor(12, spv::Op::OpFunctionCall, 0))
349fd4e5da5Sopenharmony_ci          .ToMessage();
350fd4e5da5Sopenharmony_ci
351fd4e5da5Sopenharmony_ci  // Full replay
352fd4e5da5Sopenharmony_ci  protobufs::FactSequence empty_facts;
353fd4e5da5Sopenharmony_ci  auto replayer_result =
354fd4e5da5Sopenharmony_ci      Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
355fd4e5da5Sopenharmony_ci               transformations, transformations.transformation_size(), true,
356fd4e5da5Sopenharmony_ci               validator_options)
357fd4e5da5Sopenharmony_ci          .Run();
358fd4e5da5Sopenharmony_ci  // Replay should succeed.
359fd4e5da5Sopenharmony_ci  ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete, replayer_result.status);
360fd4e5da5Sopenharmony_ci  // All transformations should be applied.
361fd4e5da5Sopenharmony_ci  ASSERT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
362fd4e5da5Sopenharmony_ci      transformations, replayer_result.applied_transformations));
363fd4e5da5Sopenharmony_ci
364fd4e5da5Sopenharmony_ci  const std::string kExpected = R"(
365fd4e5da5Sopenharmony_ci               OpCapability Shader
366fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
367fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
368fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
369fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
370fd4e5da5Sopenharmony_ci               OpSource ESSL 320
371fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
372fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
373fd4e5da5Sopenharmony_ci          %8 = OpTypeInt 32 1
374fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
375fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Private %8
376fd4e5da5Sopenharmony_ci         %11 = OpConstant %8 1
377fd4e5da5Sopenharmony_ci        %100 = OpConstant %8 42
378fd4e5da5Sopenharmony_ci        %101 = OpVariable %50 Private %100
379fd4e5da5Sopenharmony_ci        %103 = OpTypeFunction %2 %8
380fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
381fd4e5da5Sopenharmony_ci          %5 = OpLabel
382fd4e5da5Sopenharmony_ci         %10 = OpVariable %9 Function
383fd4e5da5Sopenharmony_ci               OpStore %10 %11
384fd4e5da5Sopenharmony_ci        %104 = OpCopyObject %8 %11
385fd4e5da5Sopenharmony_ci         %12 = OpFunctionCall %2 %6 %100
386fd4e5da5Sopenharmony_ci               OpReturn
387fd4e5da5Sopenharmony_ci               OpFunctionEnd
388fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %103
389fd4e5da5Sopenharmony_ci        %102 = OpFunctionParameter %8
390fd4e5da5Sopenharmony_ci          %7 = OpLabel
391fd4e5da5Sopenharmony_ci               OpReturn
392fd4e5da5Sopenharmony_ci               OpFunctionEnd
393fd4e5da5Sopenharmony_ci  )";
394fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
395fd4e5da5Sopenharmony_ci      IsEqual(env, kExpected, replayer_result.transformed_module.get()));
396fd4e5da5Sopenharmony_ci
397fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
398fd4e5da5Sopenharmony_ci      replayer_result.transformation_context->GetFactManager()->IdIsIrrelevant(
399fd4e5da5Sopenharmony_ci          100));
400fd4e5da5Sopenharmony_ci  ASSERT_TRUE(replayer_result.transformation_context->GetFactManager()
401fd4e5da5Sopenharmony_ci                  ->PointeeValueIsIrrelevant(101));
402fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
403fd4e5da5Sopenharmony_ci      replayer_result.transformation_context->GetFactManager()->IdIsIrrelevant(
404fd4e5da5Sopenharmony_ci          102));
405fd4e5da5Sopenharmony_ci  ASSERT_TRUE(
406fd4e5da5Sopenharmony_ci      replayer_result.transformation_context->GetFactManager()->IsSynonymous(
407fd4e5da5Sopenharmony_ci          MakeDataDescriptor(11, {}), MakeDataDescriptor(104, {})));
408fd4e5da5Sopenharmony_ci}
409fd4e5da5Sopenharmony_ci
410fd4e5da5Sopenharmony_ciTEST(ReplayerTest, ReplayWithOverflowIds) {
411fd4e5da5Sopenharmony_ci  const std::string kTestShader = R"(
412fd4e5da5Sopenharmony_ci               OpCapability Shader
413fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
414fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
415fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
416fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
417fd4e5da5Sopenharmony_ci               OpSource ESSL 320
418fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
419fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
420fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
421fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
422fd4e5da5Sopenharmony_ci         %50 = OpTypePointer Private %6
423fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 2
424fd4e5da5Sopenharmony_ci         %11 = OpConstant %6 0
425fd4e5da5Sopenharmony_ci         %12 = OpTypeBool
426fd4e5da5Sopenharmony_ci         %17 = OpConstant %6 1
427fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
428fd4e5da5Sopenharmony_ci          %5 = OpLabel
429fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
430fd4e5da5Sopenharmony_ci               OpStore %8 %9
431fd4e5da5Sopenharmony_ci         %10 = OpLoad %6 %8
432fd4e5da5Sopenharmony_ci         %13 = OpSGreaterThan %12 %10 %11
433fd4e5da5Sopenharmony_ci               OpSelectionMerge %15 None
434fd4e5da5Sopenharmony_ci               OpBranchConditional %13 %14 %15
435fd4e5da5Sopenharmony_ci         %14 = OpLabel
436fd4e5da5Sopenharmony_ci         %16 = OpLoad %6 %8
437fd4e5da5Sopenharmony_ci         %18 = OpIAdd %6 %16 %17
438fd4e5da5Sopenharmony_ci               OpStore %8 %18
439fd4e5da5Sopenharmony_ci               OpBranch %15
440fd4e5da5Sopenharmony_ci         %15 = OpLabel
441fd4e5da5Sopenharmony_ci               OpReturn
442fd4e5da5Sopenharmony_ci               OpFunctionEnd
443fd4e5da5Sopenharmony_ci  )";
444fd4e5da5Sopenharmony_ci
445fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
446fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
447fd4e5da5Sopenharmony_ci
448fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary_in;
449fd4e5da5Sopenharmony_ci  SpirvTools t(env);
450fd4e5da5Sopenharmony_ci  t.SetMessageConsumer(kConsoleMessageConsumer);
451fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Assemble(kTestShader, &binary_in, kFuzzAssembleOption));
452fd4e5da5Sopenharmony_ci  ASSERT_TRUE(t.Validate(binary_in));
453fd4e5da5Sopenharmony_ci
454fd4e5da5Sopenharmony_ci  protobufs::TransformationSequence transformations;
455fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
456fd4e5da5Sopenharmony_ci      TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {}).ToMessage();
457fd4e5da5Sopenharmony_ci  *transformations.add_transformation() =
458fd4e5da5Sopenharmony_ci      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 11,
459fd4e5da5Sopenharmony_ci                                      true)
460fd4e5da5Sopenharmony_ci          .ToMessage();
461fd4e5da5Sopenharmony_ci
462fd4e5da5Sopenharmony_ci  protobufs::FactSequence empty_facts;
463fd4e5da5Sopenharmony_ci  auto replayer_result =
464fd4e5da5Sopenharmony_ci      Replayer(env, kConsoleMessageConsumer, binary_in, empty_facts,
465fd4e5da5Sopenharmony_ci               transformations, transformations.transformation_size(), true,
466fd4e5da5Sopenharmony_ci               validator_options)
467fd4e5da5Sopenharmony_ci          .Run();
468fd4e5da5Sopenharmony_ci  // Replay should succeed.
469fd4e5da5Sopenharmony_ci  ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete, replayer_result.status);
470fd4e5da5Sopenharmony_ci  // All transformations should be applied.
471fd4e5da5Sopenharmony_ci  ASSERT_EQ(2, replayer_result.applied_transformations.transformation_size());
472fd4e5da5Sopenharmony_ci}
473fd4e5da5Sopenharmony_ci
474fd4e5da5Sopenharmony_ci}  // namespace
475fd4e5da5Sopenharmony_ci}  // namespace fuzz
476fd4e5da5Sopenharmony_ci}  // namespace spvtools
477