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/transformation_access_chain.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(TransformationAccessChainTest, 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" %48 %54 33fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 34fd4e5da5Sopenharmony_ci OpSource ESSL 310 35fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 36fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 37fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 38fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 2 39fd4e5da5Sopenharmony_ci %50 = OpTypeMatrix %7 2 40fd4e5da5Sopenharmony_ci %70 = OpTypePointer Function %7 41fd4e5da5Sopenharmony_ci %71 = OpTypePointer Function %50 42fd4e5da5Sopenharmony_ci %8 = OpTypeStruct %7 %6 43fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %8 44fd4e5da5Sopenharmony_ci %10 = OpTypeInt 32 1 45fd4e5da5Sopenharmony_ci %11 = OpTypePointer Function %10 46fd4e5da5Sopenharmony_ci %12 = OpTypeFunction %10 %9 %11 47fd4e5da5Sopenharmony_ci %17 = OpConstant %10 0 48fd4e5da5Sopenharmony_ci %18 = OpTypeInt 32 0 49fd4e5da5Sopenharmony_ci %19 = OpConstant %18 0 50fd4e5da5Sopenharmony_ci %20 = OpTypePointer Function %6 51fd4e5da5Sopenharmony_ci %99 = OpTypePointer Private %6 52fd4e5da5Sopenharmony_ci %29 = OpConstant %6 0 53fd4e5da5Sopenharmony_ci %30 = OpConstant %6 1 54fd4e5da5Sopenharmony_ci %31 = OpConstantComposite %7 %29 %30 55fd4e5da5Sopenharmony_ci %32 = OpConstant %6 2 56fd4e5da5Sopenharmony_ci %33 = OpConstantComposite %8 %31 %32 57fd4e5da5Sopenharmony_ci %35 = OpConstant %10 10 58fd4e5da5Sopenharmony_ci %51 = OpConstant %18 10 59fd4e5da5Sopenharmony_ci %80 = OpConstant %18 0 60fd4e5da5Sopenharmony_ci %81 = OpConstant %10 1 61fd4e5da5Sopenharmony_ci %82 = OpConstant %18 2 62fd4e5da5Sopenharmony_ci %83 = OpConstant %10 3 63fd4e5da5Sopenharmony_ci %84 = OpConstant %18 4 64fd4e5da5Sopenharmony_ci %85 = OpConstant %10 5 65fd4e5da5Sopenharmony_ci %52 = OpTypeArray %50 %51 66fd4e5da5Sopenharmony_ci %53 = OpTypePointer Private %52 67fd4e5da5Sopenharmony_ci %46 = OpConstantNull %9 68fd4e5da5Sopenharmony_ci %47 = OpTypePointer Private %8 69fd4e5da5Sopenharmony_ci %48 = OpVariable %47 Private 70fd4e5da5Sopenharmony_ci %54 = OpVariable %53 Private 71fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 72fd4e5da5Sopenharmony_ci %5 = OpLabel 73fd4e5da5Sopenharmony_ci %28 = OpVariable %9 Function 74fd4e5da5Sopenharmony_ci %34 = OpVariable %11 Function 75fd4e5da5Sopenharmony_ci %36 = OpVariable %9 Function 76fd4e5da5Sopenharmony_ci %38 = OpVariable %11 Function 77fd4e5da5Sopenharmony_ci %44 = OpCopyObject %9 %36 78fd4e5da5Sopenharmony_ci OpStore %28 %33 79fd4e5da5Sopenharmony_ci OpStore %34 %35 80fd4e5da5Sopenharmony_ci %37 = OpLoad %8 %28 81fd4e5da5Sopenharmony_ci OpStore %36 %37 82fd4e5da5Sopenharmony_ci %39 = OpLoad %10 %34 83fd4e5da5Sopenharmony_ci OpStore %38 %39 84fd4e5da5Sopenharmony_ci %40 = OpFunctionCall %10 %15 %36 %38 85fd4e5da5Sopenharmony_ci %41 = OpLoad %10 %34 86fd4e5da5Sopenharmony_ci %42 = OpIAdd %10 %41 %40 87fd4e5da5Sopenharmony_ci OpStore %34 %42 88fd4e5da5Sopenharmony_ci OpReturn 89fd4e5da5Sopenharmony_ci OpFunctionEnd 90fd4e5da5Sopenharmony_ci %15 = OpFunction %10 None %12 91fd4e5da5Sopenharmony_ci %13 = OpFunctionParameter %9 92fd4e5da5Sopenharmony_ci %14 = OpFunctionParameter %11 93fd4e5da5Sopenharmony_ci %16 = OpLabel 94fd4e5da5Sopenharmony_ci %21 = OpAccessChain %20 %13 %17 %19 95fd4e5da5Sopenharmony_ci %43 = OpCopyObject %9 %13 96fd4e5da5Sopenharmony_ci %22 = OpLoad %6 %21 97fd4e5da5Sopenharmony_ci %23 = OpConvertFToS %10 %22 98fd4e5da5Sopenharmony_ci %24 = OpLoad %10 %14 99fd4e5da5Sopenharmony_ci %25 = OpIAdd %10 %23 %24 100fd4e5da5Sopenharmony_ci OpReturnValue %25 101fd4e5da5Sopenharmony_ci OpFunctionEnd 102fd4e5da5Sopenharmony_ci )"; 103fd4e5da5Sopenharmony_ci 104fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 105fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 106fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 107fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 108fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 109fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 110fd4e5da5Sopenharmony_ci 111fd4e5da5Sopenharmony_ci // Types: 112fd4e5da5Sopenharmony_ci // Ptr | Pointee | Storage class | GLSL for pointee | Ids of this type 113fd4e5da5Sopenharmony_ci // ----+---------+---------------+---------------------+------------------ 114fd4e5da5Sopenharmony_ci // 9 | 8 | Function | struct(vec2, float) | 28, 36, 44, 13, 43 115fd4e5da5Sopenharmony_ci // 11 | 10 | Function | int | 34, 38, 14 116fd4e5da5Sopenharmony_ci // 20 | 6 | Function | float | - 117fd4e5da5Sopenharmony_ci // 99 | 6 | Private | float | - 118fd4e5da5Sopenharmony_ci // 53 | 52 | Private | mat2x2[10] | 54 119fd4e5da5Sopenharmony_ci // 47 | 8 | Private | struct(vec2, float) | 48 120fd4e5da5Sopenharmony_ci // 70 | 7 | Function | vec2 | - 121fd4e5da5Sopenharmony_ci // 71 | 59 | Function | mat2x2 | - 122fd4e5da5Sopenharmony_ci 123fd4e5da5Sopenharmony_ci // Indices 0-5 are in ids 80-85 124fd4e5da5Sopenharmony_ci 125fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 126fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 127fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant( 128fd4e5da5Sopenharmony_ci 54); 129fd4e5da5Sopenharmony_ci 130fd4e5da5Sopenharmony_ci // Check the case where the index type is not a 32-bit integer. 131fd4e5da5Sopenharmony_ci TransformationAccessChain invalid_index_example1( 132fd4e5da5Sopenharmony_ci 101, 28, {29}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0)); 133fd4e5da5Sopenharmony_ci 134fd4e5da5Sopenharmony_ci // Since the index is not a 32-bit integer type but a 32-bit float type, 135fd4e5da5Sopenharmony_ci // ValidIndexComposite should return false and thus the transformation is not 136fd4e5da5Sopenharmony_ci // applicable. 137fd4e5da5Sopenharmony_ci ASSERT_FALSE(invalid_index_example1.IsApplicable(context.get(), 138fd4e5da5Sopenharmony_ci transformation_context)); 139fd4e5da5Sopenharmony_ci 140fd4e5da5Sopenharmony_ci // Bad: id is not fresh 141fd4e5da5Sopenharmony_ci ASSERT_FALSE( 142fd4e5da5Sopenharmony_ci TransformationAccessChain( 143fd4e5da5Sopenharmony_ci 43, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 144fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 145fd4e5da5Sopenharmony_ci 146fd4e5da5Sopenharmony_ci // Bad: pointer id does not exist 147fd4e5da5Sopenharmony_ci ASSERT_FALSE( 148fd4e5da5Sopenharmony_ci TransformationAccessChain( 149fd4e5da5Sopenharmony_ci 100, 1000, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 150fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 151fd4e5da5Sopenharmony_ci 152fd4e5da5Sopenharmony_ci // Bad: pointer id is not a type 153fd4e5da5Sopenharmony_ci ASSERT_FALSE( 154fd4e5da5Sopenharmony_ci TransformationAccessChain( 155fd4e5da5Sopenharmony_ci 100, 5, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 156fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 157fd4e5da5Sopenharmony_ci 158fd4e5da5Sopenharmony_ci // Bad: pointer id is not a pointer 159fd4e5da5Sopenharmony_ci ASSERT_FALSE( 160fd4e5da5Sopenharmony_ci TransformationAccessChain( 161fd4e5da5Sopenharmony_ci 100, 23, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 162fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 163fd4e5da5Sopenharmony_ci 164fd4e5da5Sopenharmony_ci // Bad: index id does not exist 165fd4e5da5Sopenharmony_ci ASSERT_FALSE( 166fd4e5da5Sopenharmony_ci TransformationAccessChain( 167fd4e5da5Sopenharmony_ci 100, 43, {1000}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 168fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 169fd4e5da5Sopenharmony_ci 170fd4e5da5Sopenharmony_ci // Bad: index id is not a constant and the pointer refers to a struct 171fd4e5da5Sopenharmony_ci ASSERT_FALSE( 172fd4e5da5Sopenharmony_ci TransformationAccessChain( 173fd4e5da5Sopenharmony_ci 100, 43, {24}, MakeInstructionDescriptor(25, spv::Op::OpIAdd, 0)) 174fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 175fd4e5da5Sopenharmony_ci 176fd4e5da5Sopenharmony_ci // Bad: too many indices 177fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 178fd4e5da5Sopenharmony_ci 100, 43, {80, 80, 80}, 179fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 180fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 181fd4e5da5Sopenharmony_ci 182fd4e5da5Sopenharmony_ci // Bad: index id is out of bounds when accessing a struct 183fd4e5da5Sopenharmony_ci ASSERT_FALSE( 184fd4e5da5Sopenharmony_ci TransformationAccessChain( 185fd4e5da5Sopenharmony_ci 100, 43, {83, 80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 186fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 187fd4e5da5Sopenharmony_ci 188fd4e5da5Sopenharmony_ci // Bad: attempt to insert before variable 189fd4e5da5Sopenharmony_ci ASSERT_FALSE( 190fd4e5da5Sopenharmony_ci TransformationAccessChain( 191fd4e5da5Sopenharmony_ci 100, 34, {}, MakeInstructionDescriptor(36, spv::Op::OpVariable, 0)) 192fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 193fd4e5da5Sopenharmony_ci 194fd4e5da5Sopenharmony_ci // Bad: OpTypeBool must be present in the module to clamp an index 195fd4e5da5Sopenharmony_ci ASSERT_FALSE( 196fd4e5da5Sopenharmony_ci TransformationAccessChain( 197fd4e5da5Sopenharmony_ci 100, 36, {80, 81}, MakeInstructionDescriptor(37, spv::Op::OpStore, 0)) 198fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 199fd4e5da5Sopenharmony_ci 200fd4e5da5Sopenharmony_ci // Bad: pointer not available 201fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 202fd4e5da5Sopenharmony_ci 100, 43, {80}, 203fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0)) 204fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 205fd4e5da5Sopenharmony_ci 206fd4e5da5Sopenharmony_ci // Bad: instruction descriptor does not identify anything 207fd4e5da5Sopenharmony_ci ASSERT_FALSE( 208fd4e5da5Sopenharmony_ci TransformationAccessChain( 209fd4e5da5Sopenharmony_ci 100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 100)) 210fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 211fd4e5da5Sopenharmony_ci 212fd4e5da5Sopenharmony_ci#ifndef NDEBUG 213fd4e5da5Sopenharmony_ci // Bad: pointer is null 214fd4e5da5Sopenharmony_ci ASSERT_DEATH( 215fd4e5da5Sopenharmony_ci TransformationAccessChain( 216fd4e5da5Sopenharmony_ci 100, 46, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 217fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context), 218fd4e5da5Sopenharmony_ci "Access chains should not be created from null/undefined pointers"); 219fd4e5da5Sopenharmony_ci#endif 220fd4e5da5Sopenharmony_ci 221fd4e5da5Sopenharmony_ci // Bad: pointer to result type does not exist 222fd4e5da5Sopenharmony_ci ASSERT_FALSE( 223fd4e5da5Sopenharmony_ci TransformationAccessChain( 224fd4e5da5Sopenharmony_ci 100, 52, {0}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)) 225fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 226fd4e5da5Sopenharmony_ci 227fd4e5da5Sopenharmony_ci { 228fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 229fd4e5da5Sopenharmony_ci 100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)); 230fd4e5da5Sopenharmony_ci ASSERT_TRUE( 231fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 232fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 233fd4e5da5Sopenharmony_ci &transformation_context); 234fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 235fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 236fd4e5da5Sopenharmony_ci ASSERT_FALSE( 237fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100)); 238fd4e5da5Sopenharmony_ci } 239fd4e5da5Sopenharmony_ci 240fd4e5da5Sopenharmony_ci { 241fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 242fd4e5da5Sopenharmony_ci 101, 28, {81}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0)); 243fd4e5da5Sopenharmony_ci ASSERT_TRUE( 244fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 245fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 246fd4e5da5Sopenharmony_ci &transformation_context); 247fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 248fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 249fd4e5da5Sopenharmony_ci ASSERT_FALSE( 250fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101)); 251fd4e5da5Sopenharmony_ci } 252fd4e5da5Sopenharmony_ci 253fd4e5da5Sopenharmony_ci { 254fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 255fd4e5da5Sopenharmony_ci 102, 44, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 0)); 256fd4e5da5Sopenharmony_ci ASSERT_TRUE( 257fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 258fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 259fd4e5da5Sopenharmony_ci &transformation_context); 260fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 261fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 262fd4e5da5Sopenharmony_ci ASSERT_FALSE( 263fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103)); 264fd4e5da5Sopenharmony_ci } 265fd4e5da5Sopenharmony_ci 266fd4e5da5Sopenharmony_ci { 267fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 268fd4e5da5Sopenharmony_ci 103, 13, {80}, 269fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0)); 270fd4e5da5Sopenharmony_ci ASSERT_TRUE( 271fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 272fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 273fd4e5da5Sopenharmony_ci &transformation_context); 274fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 275fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 276fd4e5da5Sopenharmony_ci ASSERT_FALSE( 277fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104)); 278fd4e5da5Sopenharmony_ci } 279fd4e5da5Sopenharmony_ci 280fd4e5da5Sopenharmony_ci { 281fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 282fd4e5da5Sopenharmony_ci 104, 34, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 1)); 283fd4e5da5Sopenharmony_ci ASSERT_TRUE( 284fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 285fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 286fd4e5da5Sopenharmony_ci &transformation_context); 287fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 288fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 289fd4e5da5Sopenharmony_ci ASSERT_FALSE( 290fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105)); 291fd4e5da5Sopenharmony_ci } 292fd4e5da5Sopenharmony_ci 293fd4e5da5Sopenharmony_ci { 294fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 295fd4e5da5Sopenharmony_ci 105, 38, {}, MakeInstructionDescriptor(40, spv::Op::OpFunctionCall, 0)); 296fd4e5da5Sopenharmony_ci ASSERT_TRUE( 297fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 298fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 299fd4e5da5Sopenharmony_ci &transformation_context); 300fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 301fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 302fd4e5da5Sopenharmony_ci ASSERT_FALSE( 303fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(106)); 304fd4e5da5Sopenharmony_ci } 305fd4e5da5Sopenharmony_ci 306fd4e5da5Sopenharmony_ci { 307fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 308fd4e5da5Sopenharmony_ci 106, 14, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)); 309fd4e5da5Sopenharmony_ci ASSERT_TRUE( 310fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 311fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 312fd4e5da5Sopenharmony_ci &transformation_context); 313fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 314fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 315fd4e5da5Sopenharmony_ci ASSERT_FALSE( 316fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(107)); 317fd4e5da5Sopenharmony_ci } 318fd4e5da5Sopenharmony_ci { 319fd4e5da5Sopenharmony_ci // Check the case where the access chain's base pointer has the irrelevant 320fd4e5da5Sopenharmony_ci // pointee fact; the resulting access chain should inherit this fact. 321fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 322fd4e5da5Sopenharmony_ci 107, 54, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0)); 323fd4e5da5Sopenharmony_ci ASSERT_TRUE( 324fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 325fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 326fd4e5da5Sopenharmony_ci &transformation_context); 327fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 328fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 329fd4e5da5Sopenharmony_ci ASSERT_TRUE( 330fd4e5da5Sopenharmony_ci transformation_context.GetFactManager()->PointeeValueIsIrrelevant(54)); 331fd4e5da5Sopenharmony_ci } 332fd4e5da5Sopenharmony_ci 333fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 334fd4e5da5Sopenharmony_ci OpCapability Shader 335fd4e5da5Sopenharmony_ci OpCapability VariablePointers 336fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 337fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 338fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %48 %54 339fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 340fd4e5da5Sopenharmony_ci OpSource ESSL 310 341fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 342fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 343fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 344fd4e5da5Sopenharmony_ci %7 = OpTypeVector %6 2 345fd4e5da5Sopenharmony_ci %50 = OpTypeMatrix %7 2 346fd4e5da5Sopenharmony_ci %70 = OpTypePointer Function %7 347fd4e5da5Sopenharmony_ci %71 = OpTypePointer Function %50 348fd4e5da5Sopenharmony_ci %8 = OpTypeStruct %7 %6 349fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %8 350fd4e5da5Sopenharmony_ci %10 = OpTypeInt 32 1 351fd4e5da5Sopenharmony_ci %11 = OpTypePointer Function %10 352fd4e5da5Sopenharmony_ci %12 = OpTypeFunction %10 %9 %11 353fd4e5da5Sopenharmony_ci %17 = OpConstant %10 0 354fd4e5da5Sopenharmony_ci %18 = OpTypeInt 32 0 355fd4e5da5Sopenharmony_ci %19 = OpConstant %18 0 356fd4e5da5Sopenharmony_ci %20 = OpTypePointer Function %6 357fd4e5da5Sopenharmony_ci %99 = OpTypePointer Private %6 358fd4e5da5Sopenharmony_ci %29 = OpConstant %6 0 359fd4e5da5Sopenharmony_ci %30 = OpConstant %6 1 360fd4e5da5Sopenharmony_ci %31 = OpConstantComposite %7 %29 %30 361fd4e5da5Sopenharmony_ci %32 = OpConstant %6 2 362fd4e5da5Sopenharmony_ci %33 = OpConstantComposite %8 %31 %32 363fd4e5da5Sopenharmony_ci %35 = OpConstant %10 10 364fd4e5da5Sopenharmony_ci %51 = OpConstant %18 10 365fd4e5da5Sopenharmony_ci %80 = OpConstant %18 0 366fd4e5da5Sopenharmony_ci %81 = OpConstant %10 1 367fd4e5da5Sopenharmony_ci %82 = OpConstant %18 2 368fd4e5da5Sopenharmony_ci %83 = OpConstant %10 3 369fd4e5da5Sopenharmony_ci %84 = OpConstant %18 4 370fd4e5da5Sopenharmony_ci %85 = OpConstant %10 5 371fd4e5da5Sopenharmony_ci %52 = OpTypeArray %50 %51 372fd4e5da5Sopenharmony_ci %53 = OpTypePointer Private %52 373fd4e5da5Sopenharmony_ci %46 = OpConstantNull %9 374fd4e5da5Sopenharmony_ci %47 = OpTypePointer Private %8 375fd4e5da5Sopenharmony_ci %48 = OpVariable %47 Private 376fd4e5da5Sopenharmony_ci %54 = OpVariable %53 Private 377fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 378fd4e5da5Sopenharmony_ci %5 = OpLabel 379fd4e5da5Sopenharmony_ci %28 = OpVariable %9 Function 380fd4e5da5Sopenharmony_ci %34 = OpVariable %11 Function 381fd4e5da5Sopenharmony_ci %36 = OpVariable %9 Function 382fd4e5da5Sopenharmony_ci %38 = OpVariable %11 Function 383fd4e5da5Sopenharmony_ci %44 = OpCopyObject %9 %36 384fd4e5da5Sopenharmony_ci %102 = OpAccessChain %9 %44 385fd4e5da5Sopenharmony_ci OpStore %28 %33 386fd4e5da5Sopenharmony_ci %104 = OpAccessChain %11 %34 387fd4e5da5Sopenharmony_ci OpStore %34 %35 388fd4e5da5Sopenharmony_ci %37 = OpLoad %8 %28 389fd4e5da5Sopenharmony_ci OpStore %36 %37 390fd4e5da5Sopenharmony_ci %39 = OpLoad %10 %34 391fd4e5da5Sopenharmony_ci OpStore %38 %39 392fd4e5da5Sopenharmony_ci %105 = OpAccessChain %11 %38 393fd4e5da5Sopenharmony_ci %40 = OpFunctionCall %10 %15 %36 %38 394fd4e5da5Sopenharmony_ci %41 = OpLoad %10 %34 395fd4e5da5Sopenharmony_ci %42 = OpIAdd %10 %41 %40 396fd4e5da5Sopenharmony_ci OpStore %34 %42 397fd4e5da5Sopenharmony_ci %101 = OpAccessChain %20 %28 %81 398fd4e5da5Sopenharmony_ci OpReturn 399fd4e5da5Sopenharmony_ci OpFunctionEnd 400fd4e5da5Sopenharmony_ci %15 = OpFunction %10 None %12 401fd4e5da5Sopenharmony_ci %13 = OpFunctionParameter %9 402fd4e5da5Sopenharmony_ci %14 = OpFunctionParameter %11 403fd4e5da5Sopenharmony_ci %16 = OpLabel 404fd4e5da5Sopenharmony_ci %103 = OpAccessChain %70 %13 %80 405fd4e5da5Sopenharmony_ci %21 = OpAccessChain %20 %13 %17 %19 406fd4e5da5Sopenharmony_ci %43 = OpCopyObject %9 %13 407fd4e5da5Sopenharmony_ci %22 = OpLoad %6 %21 408fd4e5da5Sopenharmony_ci %23 = OpConvertFToS %10 %22 409fd4e5da5Sopenharmony_ci %100 = OpAccessChain %70 %43 %80 410fd4e5da5Sopenharmony_ci %106 = OpAccessChain %11 %14 411fd4e5da5Sopenharmony_ci %107 = OpAccessChain %53 %54 412fd4e5da5Sopenharmony_ci %24 = OpLoad %10 %14 413fd4e5da5Sopenharmony_ci %25 = OpIAdd %10 %23 %24 414fd4e5da5Sopenharmony_ci OpReturnValue %25 415fd4e5da5Sopenharmony_ci OpFunctionEnd 416fd4e5da5Sopenharmony_ci )"; 417fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 418fd4e5da5Sopenharmony_ci} 419fd4e5da5Sopenharmony_ci 420fd4e5da5Sopenharmony_ciTEST(TransformationAccessChainTest, StructIndexMustBeConstant) { 421fd4e5da5Sopenharmony_ci std::string shader = R"( 422fd4e5da5Sopenharmony_ci OpCapability Shader 423fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 424fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 425fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 426fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 427fd4e5da5Sopenharmony_ci OpSource ESSL 320 428fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 429fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 430fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 431fd4e5da5Sopenharmony_ci %20 = OpUndef %6 432fd4e5da5Sopenharmony_ci %7 = OpTypeStruct %6 %6 433fd4e5da5Sopenharmony_ci %8 = OpTypePointer Function %7 434fd4e5da5Sopenharmony_ci %10 = OpConstant %6 0 435fd4e5da5Sopenharmony_ci %11 = OpConstant %6 2 436fd4e5da5Sopenharmony_ci %12 = OpTypePointer Function %6 437fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 438fd4e5da5Sopenharmony_ci %5 = OpLabel 439fd4e5da5Sopenharmony_ci %9 = OpVariable %8 Function 440fd4e5da5Sopenharmony_ci OpReturn 441fd4e5da5Sopenharmony_ci OpFunctionEnd 442fd4e5da5Sopenharmony_ci )"; 443fd4e5da5Sopenharmony_ci 444fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 445fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 446fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 447fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 448fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 449fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 450fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 451fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 452fd4e5da5Sopenharmony_ci // Bad: %9 is a pointer to a struct, but %20 is not a constant. 453fd4e5da5Sopenharmony_ci ASSERT_FALSE( 454fd4e5da5Sopenharmony_ci TransformationAccessChain( 455fd4e5da5Sopenharmony_ci 100, 9, {20}, MakeInstructionDescriptor(9, spv::Op::OpReturn, 0)) 456fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 457fd4e5da5Sopenharmony_ci} 458fd4e5da5Sopenharmony_ci 459fd4e5da5Sopenharmony_ciTEST(TransformationAccessChainTest, IsomorphicStructs) { 460fd4e5da5Sopenharmony_ci std::string shader = R"( 461fd4e5da5Sopenharmony_ci OpCapability Shader 462fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 463fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 464fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %11 %12 465fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 466fd4e5da5Sopenharmony_ci OpSource ESSL 310 467fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 468fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 469fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 470fd4e5da5Sopenharmony_ci %7 = OpTypeStruct %6 471fd4e5da5Sopenharmony_ci %8 = OpTypePointer Private %7 472fd4e5da5Sopenharmony_ci %9 = OpTypeStruct %6 473fd4e5da5Sopenharmony_ci %10 = OpTypePointer Private %9 474fd4e5da5Sopenharmony_ci %11 = OpVariable %8 Private 475fd4e5da5Sopenharmony_ci %12 = OpVariable %10 Private 476fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 477fd4e5da5Sopenharmony_ci %5 = OpLabel 478fd4e5da5Sopenharmony_ci OpReturn 479fd4e5da5Sopenharmony_ci OpFunctionEnd 480fd4e5da5Sopenharmony_ci )"; 481fd4e5da5Sopenharmony_ci 482fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 483fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 484fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 485fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 486fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 487fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 488fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 489fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 490fd4e5da5Sopenharmony_ci { 491fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 492fd4e5da5Sopenharmony_ci 100, 11, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0)); 493fd4e5da5Sopenharmony_ci ASSERT_TRUE( 494fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 495fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 496fd4e5da5Sopenharmony_ci &transformation_context); 497fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 498fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 499fd4e5da5Sopenharmony_ci } 500fd4e5da5Sopenharmony_ci { 501fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 502fd4e5da5Sopenharmony_ci 101, 12, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0)); 503fd4e5da5Sopenharmony_ci ASSERT_TRUE( 504fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 505fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 506fd4e5da5Sopenharmony_ci &transformation_context); 507fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 508fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 509fd4e5da5Sopenharmony_ci } 510fd4e5da5Sopenharmony_ci 511fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 512fd4e5da5Sopenharmony_ci OpCapability Shader 513fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 514fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 515fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" %11 %12 516fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 517fd4e5da5Sopenharmony_ci OpSource ESSL 310 518fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 519fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 520fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 521fd4e5da5Sopenharmony_ci %7 = OpTypeStruct %6 522fd4e5da5Sopenharmony_ci %8 = OpTypePointer Private %7 523fd4e5da5Sopenharmony_ci %9 = OpTypeStruct %6 524fd4e5da5Sopenharmony_ci %10 = OpTypePointer Private %9 525fd4e5da5Sopenharmony_ci %11 = OpVariable %8 Private 526fd4e5da5Sopenharmony_ci %12 = OpVariable %10 Private 527fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 528fd4e5da5Sopenharmony_ci %5 = OpLabel 529fd4e5da5Sopenharmony_ci %100 = OpAccessChain %8 %11 530fd4e5da5Sopenharmony_ci %101 = OpAccessChain %10 %12 531fd4e5da5Sopenharmony_ci OpReturn 532fd4e5da5Sopenharmony_ci OpFunctionEnd 533fd4e5da5Sopenharmony_ci )"; 534fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 535fd4e5da5Sopenharmony_ci} 536fd4e5da5Sopenharmony_ci 537fd4e5da5Sopenharmony_ciTEST(TransformationAccessChainTest, ClampingVariables) { 538fd4e5da5Sopenharmony_ci std::string shader = R"( 539fd4e5da5Sopenharmony_ci OpCapability Shader 540fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 541fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 542fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" %3 543fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 544fd4e5da5Sopenharmony_ci OpSource ESSL 310 545fd4e5da5Sopenharmony_ci %4 = OpTypeVoid 546fd4e5da5Sopenharmony_ci %5 = OpTypeBool 547fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %4 548fd4e5da5Sopenharmony_ci %7 = OpTypeInt 32 1 549fd4e5da5Sopenharmony_ci %8 = OpTypeVector %7 4 550fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %8 551fd4e5da5Sopenharmony_ci %10 = OpConstant %7 0 552fd4e5da5Sopenharmony_ci %11 = OpConstant %7 1 553fd4e5da5Sopenharmony_ci %12 = OpConstant %7 3 554fd4e5da5Sopenharmony_ci %13 = OpConstant %7 2 555fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %8 %10 %11 %12 %13 556fd4e5da5Sopenharmony_ci %15 = OpTypePointer Function %7 557fd4e5da5Sopenharmony_ci %16 = OpTypeInt 32 0 558fd4e5da5Sopenharmony_ci %17 = OpConstant %16 1 559fd4e5da5Sopenharmony_ci %18 = OpConstant %16 3 560fd4e5da5Sopenharmony_ci %19 = OpTypeStruct %8 561fd4e5da5Sopenharmony_ci %20 = OpTypePointer Function %19 562fd4e5da5Sopenharmony_ci %21 = OpConstant %7 9 563fd4e5da5Sopenharmony_ci %22 = OpConstant %16 10 564fd4e5da5Sopenharmony_ci %23 = OpTypeArray %19 %22 565fd4e5da5Sopenharmony_ci %24 = OpTypePointer Function %23 566fd4e5da5Sopenharmony_ci %25 = OpTypeFloat 32 567fd4e5da5Sopenharmony_ci %26 = OpTypeVector %25 4 568fd4e5da5Sopenharmony_ci %27 = OpTypePointer Output %26 569fd4e5da5Sopenharmony_ci %3 = OpVariable %27 Output 570fd4e5da5Sopenharmony_ci %2 = OpFunction %4 None %6 571fd4e5da5Sopenharmony_ci %28 = OpLabel 572fd4e5da5Sopenharmony_ci %29 = OpVariable %9 Function 573fd4e5da5Sopenharmony_ci %30 = OpVariable %15 Function 574fd4e5da5Sopenharmony_ci %31 = OpVariable %15 Function 575fd4e5da5Sopenharmony_ci %32 = OpVariable %20 Function 576fd4e5da5Sopenharmony_ci %33 = OpVariable %15 Function 577fd4e5da5Sopenharmony_ci %34 = OpVariable %24 Function 578fd4e5da5Sopenharmony_ci OpStore %29 %14 579fd4e5da5Sopenharmony_ci OpStore %30 %10 580fd4e5da5Sopenharmony_ci %36 = OpLoad %7 %30 581fd4e5da5Sopenharmony_ci %38 = OpLoad %8 %29 582fd4e5da5Sopenharmony_ci %39 = OpCompositeConstruct %19 %38 583fd4e5da5Sopenharmony_ci %40 = OpLoad %7 %30 584fd4e5da5Sopenharmony_ci %42 = OpLoad %8 %29 585fd4e5da5Sopenharmony_ci %43 = OpCompositeConstruct %19 %42 586fd4e5da5Sopenharmony_ci %45 = OpLoad %7 %30 587fd4e5da5Sopenharmony_ci %46 = OpLoad %7 %33 588fd4e5da5Sopenharmony_ci OpReturn 589fd4e5da5Sopenharmony_ci OpFunctionEnd 590fd4e5da5Sopenharmony_ci )"; 591fd4e5da5Sopenharmony_ci 592fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_4; 593fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 594fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 595fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 596fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 597fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 598fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 599fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 600fd4e5da5Sopenharmony_ci // Bad: no ids given for clamping 601fd4e5da5Sopenharmony_ci ASSERT_FALSE( 602fd4e5da5Sopenharmony_ci TransformationAccessChain( 603fd4e5da5Sopenharmony_ci 100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0)) 604fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 605fd4e5da5Sopenharmony_ci 606fd4e5da5Sopenharmony_ci // Bad: an id given for clamping is not fresh 607fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 608fd4e5da5Sopenharmony_ci 100, 29, {17}, 609fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(36, spv::Op::OpLoad, 0), 610fd4e5da5Sopenharmony_ci {{46, 201}}) 611fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 612fd4e5da5Sopenharmony_ci 613fd4e5da5Sopenharmony_ci // Bad: an id given for clamping is not fresh 614fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 615fd4e5da5Sopenharmony_ci 100, 29, {17}, 616fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(36, spv::Op::OpLoad, 0), 617fd4e5da5Sopenharmony_ci {{200, 46}}) 618fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 619fd4e5da5Sopenharmony_ci 620fd4e5da5Sopenharmony_ci // Bad: an id given for clamping is the same as the id for the access chain 621fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 622fd4e5da5Sopenharmony_ci 100, 29, {17}, 623fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(36, spv::Op::OpLoad, 0), 624fd4e5da5Sopenharmony_ci {{100, 201}}) 625fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 626fd4e5da5Sopenharmony_ci 627fd4e5da5Sopenharmony_ci // Bad: the fresh ids given are not distinct 628fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 629fd4e5da5Sopenharmony_ci 100, 29, {17}, 630fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(36, spv::Op::OpLoad, 0), 631fd4e5da5Sopenharmony_ci {{200, 200}}) 632fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 633fd4e5da5Sopenharmony_ci 634fd4e5da5Sopenharmony_ci // Bad: not enough ids given for clamping (2 pairs needed) 635fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 636fd4e5da5Sopenharmony_ci 104, 34, {45, 10, 46}, 637fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(46, spv::Op::OpReturn, 0), 638fd4e5da5Sopenharmony_ci {{208, 209}, {209, 211}}) 639fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 640fd4e5da5Sopenharmony_ci 641fd4e5da5Sopenharmony_ci // Bad: the fresh ids given are not distinct 642fd4e5da5Sopenharmony_ci ASSERT_FALSE(TransformationAccessChain( 643fd4e5da5Sopenharmony_ci 104, 34, {45, 10, 46}, 644fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(46, spv::Op::OpReturn, 0), 645fd4e5da5Sopenharmony_ci {{208, 209}, {209, 211}}) 646fd4e5da5Sopenharmony_ci .IsApplicable(context.get(), transformation_context)); 647fd4e5da5Sopenharmony_ci 648fd4e5da5Sopenharmony_ci { 649fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 650fd4e5da5Sopenharmony_ci 100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0), 651fd4e5da5Sopenharmony_ci {{200, 201}}); 652fd4e5da5Sopenharmony_ci ASSERT_TRUE( 653fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 654fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 655fd4e5da5Sopenharmony_ci &transformation_context); 656fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 657fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 658fd4e5da5Sopenharmony_ci } 659fd4e5da5Sopenharmony_ci 660fd4e5da5Sopenharmony_ci { 661fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 662fd4e5da5Sopenharmony_ci 101, 29, {36}, MakeInstructionDescriptor(38, spv::Op::OpLoad, 0), 663fd4e5da5Sopenharmony_ci {{202, 203}}); 664fd4e5da5Sopenharmony_ci ASSERT_TRUE( 665fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 666fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 667fd4e5da5Sopenharmony_ci &transformation_context); 668fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 669fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 670fd4e5da5Sopenharmony_ci } 671fd4e5da5Sopenharmony_ci 672fd4e5da5Sopenharmony_ci { 673fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 674fd4e5da5Sopenharmony_ci 102, 32, {10, 40}, MakeInstructionDescriptor(42, spv::Op::OpLoad, 0), 675fd4e5da5Sopenharmony_ci {{204, 205}}); 676fd4e5da5Sopenharmony_ci ASSERT_TRUE( 677fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 678fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 679fd4e5da5Sopenharmony_ci &transformation_context); 680fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 681fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 682fd4e5da5Sopenharmony_ci } 683fd4e5da5Sopenharmony_ci 684fd4e5da5Sopenharmony_ci { 685fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 686fd4e5da5Sopenharmony_ci 103, 34, {11}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0), 687fd4e5da5Sopenharmony_ci {{206, 207}}); 688fd4e5da5Sopenharmony_ci ASSERT_TRUE( 689fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 690fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 691fd4e5da5Sopenharmony_ci &transformation_context); 692fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 693fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 694fd4e5da5Sopenharmony_ci } 695fd4e5da5Sopenharmony_ci 696fd4e5da5Sopenharmony_ci { 697fd4e5da5Sopenharmony_ci TransformationAccessChain transformation( 698fd4e5da5Sopenharmony_ci 104, 34, {45, 10, 46}, 699fd4e5da5Sopenharmony_ci MakeInstructionDescriptor(46, spv::Op::OpReturn, 0), 700fd4e5da5Sopenharmony_ci {{208, 209}, {210, 211}}); 701fd4e5da5Sopenharmony_ci ASSERT_TRUE( 702fd4e5da5Sopenharmony_ci transformation.IsApplicable(context.get(), transformation_context)); 703fd4e5da5Sopenharmony_ci ApplyAndCheckFreshIds(transformation, context.get(), 704fd4e5da5Sopenharmony_ci &transformation_context); 705fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 706fd4e5da5Sopenharmony_ci context.get(), validator_options, kConsoleMessageConsumer)); 707fd4e5da5Sopenharmony_ci } 708fd4e5da5Sopenharmony_ci 709fd4e5da5Sopenharmony_ci std::string after_transformation = R"( 710fd4e5da5Sopenharmony_ci OpCapability Shader 711fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 712fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 713fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" %3 714fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 715fd4e5da5Sopenharmony_ci OpSource ESSL 310 716fd4e5da5Sopenharmony_ci %4 = OpTypeVoid 717fd4e5da5Sopenharmony_ci %5 = OpTypeBool 718fd4e5da5Sopenharmony_ci %6 = OpTypeFunction %4 719fd4e5da5Sopenharmony_ci %7 = OpTypeInt 32 1 720fd4e5da5Sopenharmony_ci %8 = OpTypeVector %7 4 721fd4e5da5Sopenharmony_ci %9 = OpTypePointer Function %8 722fd4e5da5Sopenharmony_ci %10 = OpConstant %7 0 723fd4e5da5Sopenharmony_ci %11 = OpConstant %7 1 724fd4e5da5Sopenharmony_ci %12 = OpConstant %7 3 725fd4e5da5Sopenharmony_ci %13 = OpConstant %7 2 726fd4e5da5Sopenharmony_ci %14 = OpConstantComposite %8 %10 %11 %12 %13 727fd4e5da5Sopenharmony_ci %15 = OpTypePointer Function %7 728fd4e5da5Sopenharmony_ci %16 = OpTypeInt 32 0 729fd4e5da5Sopenharmony_ci %17 = OpConstant %16 1 730fd4e5da5Sopenharmony_ci %18 = OpConstant %16 3 731fd4e5da5Sopenharmony_ci %19 = OpTypeStruct %8 732fd4e5da5Sopenharmony_ci %20 = OpTypePointer Function %19 733fd4e5da5Sopenharmony_ci %21 = OpConstant %7 9 734fd4e5da5Sopenharmony_ci %22 = OpConstant %16 10 735fd4e5da5Sopenharmony_ci %23 = OpTypeArray %19 %22 736fd4e5da5Sopenharmony_ci %24 = OpTypePointer Function %23 737fd4e5da5Sopenharmony_ci %25 = OpTypeFloat 32 738fd4e5da5Sopenharmony_ci %26 = OpTypeVector %25 4 739fd4e5da5Sopenharmony_ci %27 = OpTypePointer Output %26 740fd4e5da5Sopenharmony_ci %3 = OpVariable %27 Output 741fd4e5da5Sopenharmony_ci %2 = OpFunction %4 None %6 742fd4e5da5Sopenharmony_ci %28 = OpLabel 743fd4e5da5Sopenharmony_ci %29 = OpVariable %9 Function 744fd4e5da5Sopenharmony_ci %30 = OpVariable %15 Function 745fd4e5da5Sopenharmony_ci %31 = OpVariable %15 Function 746fd4e5da5Sopenharmony_ci %32 = OpVariable %20 Function 747fd4e5da5Sopenharmony_ci %33 = OpVariable %15 Function 748fd4e5da5Sopenharmony_ci %34 = OpVariable %24 Function 749fd4e5da5Sopenharmony_ci OpStore %29 %14 750fd4e5da5Sopenharmony_ci OpStore %30 %10 751fd4e5da5Sopenharmony_ci %200 = OpULessThanEqual %5 %17 %18 752fd4e5da5Sopenharmony_ci %201 = OpSelect %16 %200 %17 %18 753fd4e5da5Sopenharmony_ci %100 = OpAccessChain %15 %29 %201 754fd4e5da5Sopenharmony_ci %36 = OpLoad %7 %30 755fd4e5da5Sopenharmony_ci %202 = OpULessThanEqual %5 %36 %12 756fd4e5da5Sopenharmony_ci %203 = OpSelect %7 %202 %36 %12 757fd4e5da5Sopenharmony_ci %101 = OpAccessChain %15 %29 %203 758fd4e5da5Sopenharmony_ci %38 = OpLoad %8 %29 759fd4e5da5Sopenharmony_ci %39 = OpCompositeConstruct %19 %38 760fd4e5da5Sopenharmony_ci %40 = OpLoad %7 %30 761fd4e5da5Sopenharmony_ci %204 = OpULessThanEqual %5 %40 %12 762fd4e5da5Sopenharmony_ci %205 = OpSelect %7 %204 %40 %12 763fd4e5da5Sopenharmony_ci %102 = OpAccessChain %15 %32 %10 %205 764fd4e5da5Sopenharmony_ci %42 = OpLoad %8 %29 765fd4e5da5Sopenharmony_ci %43 = OpCompositeConstruct %19 %42 766fd4e5da5Sopenharmony_ci %206 = OpULessThanEqual %5 %11 %21 767fd4e5da5Sopenharmony_ci %207 = OpSelect %7 %206 %11 %21 768fd4e5da5Sopenharmony_ci %103 = OpAccessChain %20 %34 %207 769fd4e5da5Sopenharmony_ci %45 = OpLoad %7 %30 770fd4e5da5Sopenharmony_ci %46 = OpLoad %7 %33 771fd4e5da5Sopenharmony_ci %208 = OpULessThanEqual %5 %45 %21 772fd4e5da5Sopenharmony_ci %209 = OpSelect %7 %208 %45 %21 773fd4e5da5Sopenharmony_ci %210 = OpULessThanEqual %5 %46 %12 774fd4e5da5Sopenharmony_ci %211 = OpSelect %7 %210 %46 %12 775fd4e5da5Sopenharmony_ci %104 = OpAccessChain %15 %34 %209 %10 %211 776fd4e5da5Sopenharmony_ci OpReturn 777fd4e5da5Sopenharmony_ci OpFunctionEnd 778fd4e5da5Sopenharmony_ci )"; 779fd4e5da5Sopenharmony_ci ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); 780fd4e5da5Sopenharmony_ci} 781fd4e5da5Sopenharmony_ci 782fd4e5da5Sopenharmony_ci} // namespace 783fd4e5da5Sopenharmony_ci} // namespace fuzz 784fd4e5da5Sopenharmony_ci} // namespace spvtools 785