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