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