-
Notifications
You must be signed in to change notification settings - Fork 664
spirv-fuzz: TransformationReplaceConstantWithUniform doesn't handle OpPhi instructions #3639
Copy link
Copy link
Closed
Description
TransformationReplaceConstantWithUniform replaces a use of some id with a value of a uniform variable. Since uniform variables always point to struct types, the transformation first needs to access struct's components. It uses OpAccessChain and OpLoad for that purpose. However, when the replaced use is an operand of some OpPhi instruction, the transformation will insert OpAccessChain and OpLoad right above the OpPhi, thus invalidating the module.
The following example demonstrates the bug.
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
OpDecorate %32 DescriptorSet 0
OpDecorate %32 Binding 0
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpConstant %6 2
%13 = OpConstant %6 4
%21 = OpConstant %6 1
%34 = OpConstant %6 0
%10 = OpTypeBool
%30 = OpTypeStruct %6
%31 = OpTypePointer Uniform %30
%32 = OpVariable %31 Uniform
%33 = OpTypePointer Uniform %6
%4 = OpFunction %2 None %3
%11 = OpLabel
OpBranch %5
%5 = OpLabel
%23 = OpPhi %6 %7 %11 %20 %15
%9 = OpSLessThan %10 %23 %13
OpLoopMerge %8 %15 None
OpBranchConditional %9 %15 %8
%15 = OpLabel
%20 = OpIAdd %6 %23 %21
OpBranch %5
%8 = 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::UniformBufferElementDescriptor descriptor;
descriptor.set_descriptor_set(0);
descriptor.set_binding(0);
descriptor.add_index(0);
protobufs::FactConstantUniform fact_constant_uniform;
fact_constant_uniform.add_constant_word(2);
*fact_constant_uniform.mutable_uniform_buffer_element_descriptor() =
descriptor;
protobufs::Fact fact;
*fact.mutable_constant_uniform_fact() = fact_constant_uniform;
ASSERT_TRUE(fact_manager.AddFact(fact, context.get()));
TransformationReplaceConstantWithUniform transformation(
MakeIdUseDescriptor(7, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0),
descriptor, 50, 51);
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
transformation.Apply(context.get(), &transformation_context);
ASSERT_FALSE(IsValid(env, context.get()));The error message is
error: line 27: OpPhi must appear within a non-entry block before all non-OpPhi instructions (except for OpLine, which can be mixed with OpPhi).
%23 = OpPhi %int %51 %11 %20 %15
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels