blob: 3155b1891f26babf6c52b4f5bc98f54ede3cb1af [file] [log] [blame]
// 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_equation_instruction.h"
#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationEquationInstructionTest, SignedNegate) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpConstant %6 24
%40 = OpTypeBool
%41 = OpConstantTrue %40
%20 = OpUndef %6
%12 = OpFunction %2 None %3
%13 = OpLabel
%30 = OpCopyObject %6 %7
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
// Bad: id already in use.
ASSERT_FALSE(TransformationEquationInstruction(7, SpvOpSNegate, {7},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: identified instruction does not exist.
ASSERT_FALSE(
TransformationEquationInstruction(
14, SpvOpSNegate, {7}, MakeInstructionDescriptor(13, SpvOpLoad, 0))
.IsApplicable(context.get(), transformation_context));
// Bad: id 100 does not exist
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {100},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: id 20 is an OpUndef
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {20},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: id 30 is not available right before its definition
ASSERT_FALSE(TransformationEquationInstruction(
14, SpvOpSNegate, {30},
MakeInstructionDescriptor(30, SpvOpCopyObject, 0))
.IsApplicable(context.get(), transformation_context));
// Bad: too many arguments to OpSNegate.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {7, 7},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: 40 is a type id.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {40},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: wrong type of argument to OpSNegate.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {41},
return_instruction)
.IsApplicable(context.get(), transformation_context));
auto transformation1 = TransformationEquationInstruction(
14, SpvOpSNegate, {7}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
15, SpvOpSNegate, {14}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpConstant %6 24
%40 = OpTypeBool
%41 = OpConstantTrue %40
%20 = OpUndef %6
%12 = OpFunction %2 None %3
%13 = OpLabel
%30 = OpCopyObject %6 %7
%14 = OpSNegate %6 %7
%15 = OpSNegate %6 %14
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationEquationInstructionTest, LogicalNot) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeBool
%7 = OpConstantTrue %6
%20 = OpTypeInt 32 0
%21 = OpConstant %20 5
%12 = OpFunction %2 None %3
%13 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
// Bad: too few arguments to OpLogicalNot.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: 6 is a type id.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {6},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: wrong type of argument to OpLogicalNot.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {21},
return_instruction)
.IsApplicable(context.get(), transformation_context));
auto transformation1 = TransformationEquationInstruction(
14, SpvOpLogicalNot, {7}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
15, SpvOpLogicalNot, {14}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeBool
%7 = OpConstantTrue %6
%20 = OpTypeInt 32 0
%21 = OpConstant %20 5
%12 = OpFunction %2 None %3
%13 = OpLabel
%14 = OpLogicalNot %6 %7
%15 = OpLogicalNot %6 %14
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationEquationInstructionTest, AddSubNegate1) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%30 = OpTypeVector %6 3
%15 = OpConstant %6 24
%16 = OpConstant %6 37
%31 = OpConstantComposite %30 %15 %16 %15
%33 = OpTypeBool
%32 = OpConstantTrue %33
%12 = OpFunction %2 None %3
%13 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
// Bad: too many arguments to OpIAdd.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 16, 16},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: boolean argument to OpIAdd.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 32},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: type as argument to OpIAdd.
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {33, 16},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: arguments of mismatched widths
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 31},
return_instruction)
.IsApplicable(context.get(), transformation_context));
// Bad: arguments of mismatched widths
ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {31, 15},
return_instruction)
.IsApplicable(context.get(), transformation_context));
auto transformation1 = TransformationEquationInstruction(
14, SpvOpIAdd, {15, 16}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
19, SpvOpISub, {14, 16}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {}), context.get()));
auto transformation3 = TransformationEquationInstruction(
20, SpvOpISub, {14, 15}, return_instruction);
ASSERT_TRUE(
transformation3.IsApplicable(context.get(), transformation_context));
transformation3.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
auto transformation4 = TransformationEquationInstruction(
22, SpvOpISub, {16, 14}, return_instruction);
ASSERT_TRUE(
transformation4.IsApplicable(context.get(), transformation_context));
transformation4.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation5 = TransformationEquationInstruction(
24, SpvOpSNegate, {22}, return_instruction);
ASSERT_TRUE(
transformation5.IsApplicable(context.get(), transformation_context));
transformation5.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {}), context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%30 = OpTypeVector %6 3
%15 = OpConstant %6 24
%16 = OpConstant %6 37
%31 = OpConstantComposite %30 %15 %16 %15
%33 = OpTypeBool
%32 = OpConstantTrue %33
%12 = OpFunction %2 None %3
%13 = OpLabel
%14 = OpIAdd %6 %15 %16
%19 = OpISub %6 %14 %16 ; ==> synonymous(%19, %15)
%20 = OpISub %6 %14 %15 ; ==> synonymous(%20, %16)
%22 = OpISub %6 %16 %14
%24 = OpSNegate %6 %22 ; ==> synonymous(%24, %15)
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationEquationInstructionTest, AddSubNegate2) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%15 = OpConstant %6 24
%16 = OpConstant %6 37
%12 = OpFunction %2 None %3
%13 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
auto transformation1 = TransformationEquationInstruction(
14, SpvOpISub, {15, 16}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
17, SpvOpIAdd, {14, 16}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {}), context.get()));
auto transformation3 = TransformationEquationInstruction(
18, SpvOpIAdd, {16, 14}, return_instruction);
ASSERT_TRUE(
transformation3.IsApplicable(context.get(), transformation_context));
transformation3.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {}), context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {}), context.get()));
auto transformation4 = TransformationEquationInstruction(
19, SpvOpISub, {14, 15}, return_instruction);
ASSERT_TRUE(
transformation4.IsApplicable(context.get(), transformation_context));
transformation4.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation5 = TransformationEquationInstruction(
20, SpvOpSNegate, {19}, return_instruction);
ASSERT_TRUE(
transformation5.IsApplicable(context.get(), transformation_context));
transformation5.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
auto transformation6 = TransformationEquationInstruction(
21, SpvOpISub, {14, 19}, return_instruction);
ASSERT_TRUE(
transformation6.IsApplicable(context.get(), transformation_context));
transformation6.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {}), context.get()));
auto transformation7 = TransformationEquationInstruction(
22, SpvOpISub, {14, 18}, return_instruction);
ASSERT_TRUE(
transformation7.IsApplicable(context.get(), transformation_context));
transformation7.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation8 = TransformationEquationInstruction(
23, SpvOpSNegate, {22}, return_instruction);
ASSERT_TRUE(
transformation8.IsApplicable(context.get(), transformation_context));
transformation8.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {}), context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%15 = OpConstant %6 24
%16 = OpConstant %6 37
%12 = OpFunction %2 None %3
%13 = OpLabel
%14 = OpISub %6 %15 %16
%17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
%18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
%19 = OpISub %6 %14 %15
%20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
%21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
%22 = OpISub %6 %14 %18
%23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationEquationInstructionTest, Miscellaneous1) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%113 = OpConstant %6 24
%12 = OpFunction %2 None %3
%13 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
auto transformation1 = TransformationEquationInstruction(
522, SpvOpISub, {113, 113}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
570, SpvOpIAdd, {522, 113}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%113 = OpConstant %6 24
%12 = OpFunction %2 None %3
%13 = OpLabel
%522 = OpISub %6 %113 %113
%570 = OpIAdd %6 %522 %113
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {}), context.get()));
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
TEST(TransformationEquationInstructionTest, Miscellaneous2) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%113 = OpConstant %6 24
%12 = OpFunction %2 None %3
%13 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
protobufs::InstructionDescriptor return_instruction =
MakeInstructionDescriptor(13, SpvOpReturn, 0);
auto transformation1 = TransformationEquationInstruction(
522, SpvOpISub, {113, 113}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
transformation1.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
auto transformation2 = TransformationEquationInstruction(
570, SpvOpIAdd, {522, 113}, return_instruction);
ASSERT_TRUE(
transformation2.IsApplicable(context.get(), transformation_context));
transformation2.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %12 "main"
OpExecutionMode %12 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%113 = OpConstant %6 24
%12 = OpFunction %2 None %3
%13 = OpLabel
%522 = OpISub %6 %113 %113
%570 = OpIAdd %6 %522 %113
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {}), context.get()));
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools