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