| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784 |
- // Copyright (c) 2020 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "source/fuzz/transformation_access_chain.h"
- #include "gtest/gtest.h"
- #include "source/fuzz/fuzzer_util.h"
- #include "source/fuzz/instruction_descriptor.h"
- #include "test/fuzz/fuzz_test_util.h"
- namespace spvtools {
- namespace fuzz {
- namespace {
- TEST(TransformationAccessChainTest, BasicTest) {
- std::string shader = R"(
- OpCapability Shader
- OpCapability VariablePointers
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %48 %54
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeVector %6 2
- %50 = OpTypeMatrix %7 2
- %70 = OpTypePointer Function %7
- %71 = OpTypePointer Function %50
- %8 = OpTypeStruct %7 %6
- %9 = OpTypePointer Function %8
- %10 = OpTypeInt 32 1
- %11 = OpTypePointer Function %10
- %12 = OpTypeFunction %10 %9 %11
- %17 = OpConstant %10 0
- %18 = OpTypeInt 32 0
- %19 = OpConstant %18 0
- %20 = OpTypePointer Function %6
- %99 = OpTypePointer Private %6
- %29 = OpConstant %6 0
- %30 = OpConstant %6 1
- %31 = OpConstantComposite %7 %29 %30
- %32 = OpConstant %6 2
- %33 = OpConstantComposite %8 %31 %32
- %35 = OpConstant %10 10
- %51 = OpConstant %18 10
- %80 = OpConstant %18 0
- %81 = OpConstant %10 1
- %82 = OpConstant %18 2
- %83 = OpConstant %10 3
- %84 = OpConstant %18 4
- %85 = OpConstant %10 5
- %52 = OpTypeArray %50 %51
- %53 = OpTypePointer Private %52
- %46 = OpConstantNull %9
- %47 = OpTypePointer Private %8
- %48 = OpVariable %47 Private
- %54 = OpVariable %53 Private
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %28 = OpVariable %9 Function
- %34 = OpVariable %11 Function
- %36 = OpVariable %9 Function
- %38 = OpVariable %11 Function
- %44 = OpCopyObject %9 %36
- OpStore %28 %33
- OpStore %34 %35
- %37 = OpLoad %8 %28
- OpStore %36 %37
- %39 = OpLoad %10 %34
- OpStore %38 %39
- %40 = OpFunctionCall %10 %15 %36 %38
- %41 = OpLoad %10 %34
- %42 = OpIAdd %10 %41 %40
- OpStore %34 %42
- OpReturn
- OpFunctionEnd
- %15 = OpFunction %10 None %12
- %13 = OpFunctionParameter %9
- %14 = OpFunctionParameter %11
- %16 = OpLabel
- %21 = OpAccessChain %20 %13 %17 %19
- %43 = OpCopyObject %9 %13
- %22 = OpLoad %6 %21
- %23 = OpConvertFToS %10 %22
- %24 = OpLoad %10 %14
- %25 = OpIAdd %10 %23 %24
- OpReturnValue %25
- OpFunctionEnd
- )";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- // Types:
- // Ptr | Pointee | Storage class | GLSL for pointee | Ids of this type
- // ----+---------+---------------+---------------------+------------------
- // 9 | 8 | Function | struct(vec2, float) | 28, 36, 44, 13, 43
- // 11 | 10 | Function | int | 34, 38, 14
- // 20 | 6 | Function | float | -
- // 99 | 6 | Private | float | -
- // 53 | 52 | Private | mat2x2[10] | 54
- // 47 | 8 | Private | struct(vec2, float) | 48
- // 70 | 7 | Function | vec2 | -
- // 71 | 59 | Function | mat2x2 | -
- // Indices 0-5 are in ids 80-85
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
- 54);
- // Check the case where the index type is not a 32-bit integer.
- TransformationAccessChain invalid_index_example1(
- 101, 28, {29}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
- // Since the index is not a 32-bit integer type but a 32-bit float type,
- // ValidIndexComposite should return false and thus the transformation is not
- // applicable.
- ASSERT_FALSE(invalid_index_example1.IsApplicable(context.get(),
- transformation_context));
- // Bad: id is not fresh
- ASSERT_FALSE(
- TransformationAccessChain(
- 43, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: pointer id does not exist
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 1000, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: pointer id is not a type
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 5, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: pointer id is not a pointer
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 23, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: index id does not exist
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 43, {1000}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: index id is not a constant and the pointer refers to a struct
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 43, {24}, MakeInstructionDescriptor(25, spv::Op::OpIAdd, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: too many indices
- ASSERT_FALSE(TransformationAccessChain(
- 100, 43, {80, 80, 80},
- MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: index id is out of bounds when accessing a struct
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 43, {83, 80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: attempt to insert before variable
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 34, {}, MakeInstructionDescriptor(36, spv::Op::OpVariable, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: OpTypeBool must be present in the module to clamp an index
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 36, {80, 81}, MakeInstructionDescriptor(37, spv::Op::OpStore, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: pointer not available
- ASSERT_FALSE(TransformationAccessChain(
- 100, 43, {80},
- MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: instruction descriptor does not identify anything
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 100))
- .IsApplicable(context.get(), transformation_context));
- #ifndef NDEBUG
- // Bad: pointer is null
- ASSERT_DEATH(
- TransformationAccessChain(
- 100, 46, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context),
- "Access chains should not be created from null/undefined pointers");
- #endif
- // Bad: pointer to result type does not exist
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 52, {0}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- {
- TransformationAccessChain transformation(
- 100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
- }
- {
- TransformationAccessChain transformation(
- 101, 28, {81}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
- }
- {
- TransformationAccessChain transformation(
- 102, 44, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103));
- }
- {
- TransformationAccessChain transformation(
- 103, 13, {80},
- MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104));
- }
- {
- TransformationAccessChain transformation(
- 104, 34, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 1));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105));
- }
- {
- TransformationAccessChain transformation(
- 105, 38, {}, MakeInstructionDescriptor(40, spv::Op::OpFunctionCall, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(106));
- }
- {
- TransformationAccessChain transformation(
- 106, 14, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(107));
- }
- {
- // Check the case where the access chain's base pointer has the irrelevant
- // pointee fact; the resulting access chain should inherit this fact.
- TransformationAccessChain transformation(
- 107, 54, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- ASSERT_TRUE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(54));
- }
- std::string after_transformation = R"(
- OpCapability Shader
- OpCapability VariablePointers
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %48 %54
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeVector %6 2
- %50 = OpTypeMatrix %7 2
- %70 = OpTypePointer Function %7
- %71 = OpTypePointer Function %50
- %8 = OpTypeStruct %7 %6
- %9 = OpTypePointer Function %8
- %10 = OpTypeInt 32 1
- %11 = OpTypePointer Function %10
- %12 = OpTypeFunction %10 %9 %11
- %17 = OpConstant %10 0
- %18 = OpTypeInt 32 0
- %19 = OpConstant %18 0
- %20 = OpTypePointer Function %6
- %99 = OpTypePointer Private %6
- %29 = OpConstant %6 0
- %30 = OpConstant %6 1
- %31 = OpConstantComposite %7 %29 %30
- %32 = OpConstant %6 2
- %33 = OpConstantComposite %8 %31 %32
- %35 = OpConstant %10 10
- %51 = OpConstant %18 10
- %80 = OpConstant %18 0
- %81 = OpConstant %10 1
- %82 = OpConstant %18 2
- %83 = OpConstant %10 3
- %84 = OpConstant %18 4
- %85 = OpConstant %10 5
- %52 = OpTypeArray %50 %51
- %53 = OpTypePointer Private %52
- %46 = OpConstantNull %9
- %47 = OpTypePointer Private %8
- %48 = OpVariable %47 Private
- %54 = OpVariable %53 Private
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %28 = OpVariable %9 Function
- %34 = OpVariable %11 Function
- %36 = OpVariable %9 Function
- %38 = OpVariable %11 Function
- %44 = OpCopyObject %9 %36
- %102 = OpAccessChain %9 %44
- OpStore %28 %33
- %104 = OpAccessChain %11 %34
- OpStore %34 %35
- %37 = OpLoad %8 %28
- OpStore %36 %37
- %39 = OpLoad %10 %34
- OpStore %38 %39
- %105 = OpAccessChain %11 %38
- %40 = OpFunctionCall %10 %15 %36 %38
- %41 = OpLoad %10 %34
- %42 = OpIAdd %10 %41 %40
- OpStore %34 %42
- %101 = OpAccessChain %20 %28 %81
- OpReturn
- OpFunctionEnd
- %15 = OpFunction %10 None %12
- %13 = OpFunctionParameter %9
- %14 = OpFunctionParameter %11
- %16 = OpLabel
- %103 = OpAccessChain %70 %13 %80
- %21 = OpAccessChain %20 %13 %17 %19
- %43 = OpCopyObject %9 %13
- %22 = OpLoad %6 %21
- %23 = OpConvertFToS %10 %22
- %100 = OpAccessChain %70 %43 %80
- %106 = OpAccessChain %11 %14
- %107 = OpAccessChain %53 %54
- %24 = OpLoad %10 %14
- %25 = OpIAdd %10 %23 %24
- OpReturnValue %25
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
- }
- TEST(TransformationAccessChainTest, StructIndexMustBeConstant) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 320
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeInt 32 1
- %20 = OpUndef %6
- %7 = OpTypeStruct %6 %6
- %8 = OpTypePointer Function %7
- %10 = OpConstant %6 0
- %11 = OpConstant %6 2
- %12 = OpTypePointer Function %6
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %9 = OpVariable %8 Function
- OpReturn
- OpFunctionEnd
- )";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- // Bad: %9 is a pointer to a struct, but %20 is not a constant.
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 9, {20}, MakeInstructionDescriptor(9, spv::Op::OpReturn, 0))
- .IsApplicable(context.get(), transformation_context));
- }
- TEST(TransformationAccessChainTest, IsomorphicStructs) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %11 %12
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6
- %8 = OpTypePointer Private %7
- %9 = OpTypeStruct %6
- %10 = OpTypePointer Private %9
- %11 = OpVariable %8 Private
- %12 = OpVariable %10 Private
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- {
- TransformationAccessChain transformation(
- 100, 11, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- {
- TransformationAccessChain transformation(
- 101, 12, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %11 %12
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6
- %8 = OpTypePointer Private %7
- %9 = OpTypeStruct %6
- %10 = OpTypePointer Private %9
- %11 = OpVariable %8 Private
- %12 = OpVariable %10 Private
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %100 = OpAccessChain %8 %11
- %101 = OpAccessChain %10 %12
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
- }
- TEST(TransformationAccessChainTest, ClampingVariables) {
- std::string shader = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %2 "main" %3
- OpExecutionMode %2 OriginUpperLeft
- OpSource ESSL 310
- %4 = OpTypeVoid
- %5 = OpTypeBool
- %6 = OpTypeFunction %4
- %7 = OpTypeInt 32 1
- %8 = OpTypeVector %7 4
- %9 = OpTypePointer Function %8
- %10 = OpConstant %7 0
- %11 = OpConstant %7 1
- %12 = OpConstant %7 3
- %13 = OpConstant %7 2
- %14 = OpConstantComposite %8 %10 %11 %12 %13
- %15 = OpTypePointer Function %7
- %16 = OpTypeInt 32 0
- %17 = OpConstant %16 1
- %18 = OpConstant %16 3
- %19 = OpTypeStruct %8
- %20 = OpTypePointer Function %19
- %21 = OpConstant %7 9
- %22 = OpConstant %16 10
- %23 = OpTypeArray %19 %22
- %24 = OpTypePointer Function %23
- %25 = OpTypeFloat 32
- %26 = OpTypeVector %25 4
- %27 = OpTypePointer Output %26
- %3 = OpVariable %27 Output
- %2 = OpFunction %4 None %6
- %28 = OpLabel
- %29 = OpVariable %9 Function
- %30 = OpVariable %15 Function
- %31 = OpVariable %15 Function
- %32 = OpVariable %20 Function
- %33 = OpVariable %15 Function
- %34 = OpVariable %24 Function
- OpStore %29 %14
- OpStore %30 %10
- %36 = OpLoad %7 %30
- %38 = OpLoad %8 %29
- %39 = OpCompositeConstruct %19 %38
- %40 = OpLoad %7 %30
- %42 = OpLoad %8 %29
- %43 = OpCompositeConstruct %19 %42
- %45 = OpLoad %7 %30
- %46 = OpLoad %7 %33
- OpReturn
- OpFunctionEnd
- )";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- // Bad: no ids given for clamping
- ASSERT_FALSE(
- TransformationAccessChain(
- 100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0))
- .IsApplicable(context.get(), transformation_context));
- // Bad: an id given for clamping is not fresh
- ASSERT_FALSE(TransformationAccessChain(
- 100, 29, {17},
- MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
- {{46, 201}})
- .IsApplicable(context.get(), transformation_context));
- // Bad: an id given for clamping is not fresh
- ASSERT_FALSE(TransformationAccessChain(
- 100, 29, {17},
- MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
- {{200, 46}})
- .IsApplicable(context.get(), transformation_context));
- // Bad: an id given for clamping is the same as the id for the access chain
- ASSERT_FALSE(TransformationAccessChain(
- 100, 29, {17},
- MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
- {{100, 201}})
- .IsApplicable(context.get(), transformation_context));
- // Bad: the fresh ids given are not distinct
- ASSERT_FALSE(TransformationAccessChain(
- 100, 29, {17},
- MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
- {{200, 200}})
- .IsApplicable(context.get(), transformation_context));
- // Bad: not enough ids given for clamping (2 pairs needed)
- ASSERT_FALSE(TransformationAccessChain(
- 104, 34, {45, 10, 46},
- MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
- {{208, 209}, {209, 211}})
- .IsApplicable(context.get(), transformation_context));
- // Bad: the fresh ids given are not distinct
- ASSERT_FALSE(TransformationAccessChain(
- 104, 34, {45, 10, 46},
- MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
- {{208, 209}, {209, 211}})
- .IsApplicable(context.get(), transformation_context));
- {
- TransformationAccessChain transformation(
- 100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
- {{200, 201}});
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- {
- TransformationAccessChain transformation(
- 101, 29, {36}, MakeInstructionDescriptor(38, spv::Op::OpLoad, 0),
- {{202, 203}});
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- {
- TransformationAccessChain transformation(
- 102, 32, {10, 40}, MakeInstructionDescriptor(42, spv::Op::OpLoad, 0),
- {{204, 205}});
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- {
- TransformationAccessChain transformation(
- 103, 34, {11}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0),
- {{206, 207}});
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- {
- TransformationAccessChain transformation(
- 104, 34, {45, 10, 46},
- MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
- {{208, 209}, {210, 211}});
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
- context.get(), validator_options, kConsoleMessageConsumer));
- }
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %2 "main" %3
- OpExecutionMode %2 OriginUpperLeft
- OpSource ESSL 310
- %4 = OpTypeVoid
- %5 = OpTypeBool
- %6 = OpTypeFunction %4
- %7 = OpTypeInt 32 1
- %8 = OpTypeVector %7 4
- %9 = OpTypePointer Function %8
- %10 = OpConstant %7 0
- %11 = OpConstant %7 1
- %12 = OpConstant %7 3
- %13 = OpConstant %7 2
- %14 = OpConstantComposite %8 %10 %11 %12 %13
- %15 = OpTypePointer Function %7
- %16 = OpTypeInt 32 0
- %17 = OpConstant %16 1
- %18 = OpConstant %16 3
- %19 = OpTypeStruct %8
- %20 = OpTypePointer Function %19
- %21 = OpConstant %7 9
- %22 = OpConstant %16 10
- %23 = OpTypeArray %19 %22
- %24 = OpTypePointer Function %23
- %25 = OpTypeFloat 32
- %26 = OpTypeVector %25 4
- %27 = OpTypePointer Output %26
- %3 = OpVariable %27 Output
- %2 = OpFunction %4 None %6
- %28 = OpLabel
- %29 = OpVariable %9 Function
- %30 = OpVariable %15 Function
- %31 = OpVariable %15 Function
- %32 = OpVariable %20 Function
- %33 = OpVariable %15 Function
- %34 = OpVariable %24 Function
- OpStore %29 %14
- OpStore %30 %10
- %200 = OpULessThanEqual %5 %17 %18
- %201 = OpSelect %16 %200 %17 %18
- %100 = OpAccessChain %15 %29 %201
- %36 = OpLoad %7 %30
- %202 = OpULessThanEqual %5 %36 %12
- %203 = OpSelect %7 %202 %36 %12
- %101 = OpAccessChain %15 %29 %203
- %38 = OpLoad %8 %29
- %39 = OpCompositeConstruct %19 %38
- %40 = OpLoad %7 %30
- %204 = OpULessThanEqual %5 %40 %12
- %205 = OpSelect %7 %204 %40 %12
- %102 = OpAccessChain %15 %32 %10 %205
- %42 = OpLoad %8 %29
- %43 = OpCompositeConstruct %19 %42
- %206 = OpULessThanEqual %5 %11 %21
- %207 = OpSelect %7 %206 %11 %21
- %103 = OpAccessChain %20 %34 %207
- %45 = OpLoad %7 %30
- %46 = OpLoad %7 %33
- %208 = OpULessThanEqual %5 %45 %21
- %209 = OpSelect %7 %208 %45 %21
- %210 = OpULessThanEqual %5 %46 %12
- %211 = OpSelect %7 %210 %46 %12
- %104 = OpAccessChain %15 %34 %209 %10 %211
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
- }
- } // namespace
- } // namespace fuzz
- } // namespace spvtools
|