spirv-fuzz: Refactor variable creation (#3414)
Fixes #3413.
diff --git a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
index ad8a8f2..0501456 100644
--- a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
+++ b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
@@ -104,13 +104,37 @@
// If the pointer type does not exist, then create it.
FindOrCreatePointerType(basic_type_id, variable_storage_class);
+ // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3403):
+ // type support here is limited by the FindOrCreateZeroConstant
+ // function.
+ const auto* type_inst =
+ GetIRContext()->get_def_use_mgr()->GetDef(basic_type_id);
+ assert(type_inst);
+ switch (type_inst->opcode()) {
+ case SpvOpTypeBool:
+ case SpvOpTypeFloat:
+ case SpvOpTypeInt:
+ case SpvOpTypeArray:
+ case SpvOpTypeMatrix:
+ case SpvOpTypeVector:
+ case SpvOpTypeStruct:
+ break;
+ default:
+ return;
+ }
+
+ // Create a constant to initialize the variable from. This might update
+ // module's id bound so it must be done before any fresh ids are
+ // computed.
+ auto initializer_id = FindOrCreateZeroConstant(basic_type_id);
+
// Applies the push id through variable transformation.
ApplyTransformation(TransformationPushIdThroughVariable(
value_instructions[GetFuzzerContext()->RandomIndex(
value_instructions)]
->result_id(),
GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(),
- variable_storage_class, instruction_descriptor));
+ variable_storage_class, initializer_id, instruction_descriptor));
});
}
diff --git a/source/fuzz/fuzzer_pass_push_ids_through_variables.h b/source/fuzz/fuzzer_pass_push_ids_through_variables.h
index ffec89e..3ad5404 100644
--- a/source/fuzz/fuzzer_pass_push_ids_through_variables.h
+++ b/source/fuzz/fuzzer_pass_push_ids_through_variables.h
@@ -30,7 +30,7 @@
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPushIdsThroughVariables();
+ ~FuzzerPassPushIdsThroughVariables() override;
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index a5475d1..435ac04 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -583,6 +583,75 @@
}
}
+void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, SpvStorageClass storage_class,
+ uint32_t initializer_id) {
+ // Check various preconditions.
+ assert((storage_class == SpvStorageClassPrivate ||
+ storage_class == SpvStorageClassWorkgroup) &&
+ "Variable's storage class must be either Private or Workgroup");
+
+ auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
+ (void)type_inst; // Variable becomes unused in release mode.
+ assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
+ GetStorageClassFromPointerType(type_inst) == storage_class &&
+ "Variable's type is invalid");
+
+ if (storage_class == SpvStorageClassWorkgroup) {
+ assert(initializer_id == 0);
+ }
+
+ if (initializer_id != 0) {
+ const auto* constant_inst =
+ context->get_def_use_mgr()->GetDef(initializer_id);
+ (void)constant_inst; // Variable becomes unused in release mode.
+ assert(constant_inst && spvOpcodeIsConstant(constant_inst->opcode()) &&
+ GetPointeeTypeIdFromPointerType(type_inst) ==
+ constant_inst->type_id() &&
+ "Initializer is invalid");
+ }
+
+ opt::Instruction::OperandList operands = {
+ {SPV_OPERAND_TYPE_STORAGE_CLASS, {static_cast<uint32_t>(storage_class)}}};
+
+ if (initializer_id) {
+ operands.push_back({SPV_OPERAND_TYPE_ID, {initializer_id}});
+ }
+
+ context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ context, SpvOpVariable, type_id, result_id, std::move(operands)));
+
+ AddVariableIdToEntryPointInterfaces(context, result_id);
+}
+
+void AddLocalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, uint32_t function_id,
+ uint32_t initializer_id) {
+ // Check various preconditions.
+ auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
+ (void)type_inst; // Variable becomes unused in release mode.
+ assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
+ GetStorageClassFromPointerType(type_inst) == SpvStorageClassFunction &&
+ "Variable's type is invalid");
+
+ const auto* constant_inst =
+ context->get_def_use_mgr()->GetDef(initializer_id);
+ (void)constant_inst; // Variable becomes unused in release mode.
+ assert(constant_inst && spvOpcodeIsConstant(constant_inst->opcode()) &&
+ GetPointeeTypeIdFromPointerType(type_inst) ==
+ constant_inst->type_id() &&
+ "Initializer is invalid");
+
+ auto* function = FindFunction(context, function_id);
+ assert(function && "Function id is invalid");
+
+ function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
+ context, SpvOpVariable, type_id, result_id,
+ opt::Instruction::OperandList{
+ {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
+ {SPV_OPERAND_TYPE_ID, {initializer_id}}}));
+}
+
} // namespace fuzzerutil
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_util.h b/source/fuzz/fuzzer_util.h
index fb2686b..77e390e 100644
--- a/source/fuzz/fuzzer_util.h
+++ b/source/fuzz/fuzzer_util.h
@@ -226,6 +226,32 @@
// from an entry point function, to be listed in that function's interface.
void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id);
+// Adds a global variable with storage class |storage_class| to the module, with
+// type |type_id| and either no initializer or |initializer_id| as an
+// initializer, depending on whether |initializer_id| is 0. The global variable
+// has result id |result_id|.
+//
+// - |type_id| must be the id of a pointer type with the same storage class as
+// |storage_class|.
+// - |storage_class| must be Private or Workgroup.
+// - |initializer_id| must be 0 if |storage_class| is Workgroup, and otherwise
+// may either be 0 or the id of a constant whose type is the pointee type of
+// |type_id|.
+void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, SpvStorageClass storage_class,
+ uint32_t initializer_id);
+
+// Adds an instruction to the start of |function_id|, of the form:
+// |result_id| = OpVariable |type_id| Function |initializer_id|.
+//
+// - |type_id| must be the id of a pointer type with Function storage class.
+// - |initializer_id| must be the id of a constant with the same type as the
+// pointer's pointee type.
+// - |function_id| must be the id of a function.
+void AddLocalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, uint32_t function_id,
+ uint32_t initializer_id);
+
} // namespace fuzzerutil
} // namespace fuzz
diff --git a/source/fuzz/protobufs/spvtoolsfuzz.proto b/source/fuzz/protobufs/spvtoolsfuzz.proto
index 1fa2005..9ebabf7 100644
--- a/source/fuzz/protobufs/spvtoolsfuzz.proto
+++ b/source/fuzz/protobufs/spvtoolsfuzz.proto
@@ -1020,12 +1020,15 @@
// A fresh id for the variable to be stored to.
uint32 variable_id = 3;
+ // Constant to initialize the variable from.
+ uint32 initializer_id = 4;
+
// The variable storage class (global or local).
- uint32 variable_storage_class = 4;
+ uint32 variable_storage_class = 5;
// A descriptor for an instruction which the new OpStore
// and OpLoad instructions might be inserted before.
- InstructionDescriptor instruction_descriptor = 5;
+ InstructionDescriptor instruction_descriptor = 6;
}
diff --git a/source/fuzz/transformation_add_global_variable.cpp b/source/fuzz/transformation_add_global_variable.cpp
index 077ed6b..b69f208 100644
--- a/source/fuzz/transformation_add_global_variable.cpp
+++ b/source/fuzz/transformation_add_global_variable.cpp
@@ -93,20 +93,12 @@
void TransformationAddGlobalVariable::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- opt::Instruction::OperandList input_operands;
- input_operands.push_back(
- {SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}});
- if (message_.initializer_id()) {
- input_operands.push_back(
- {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}});
- }
- ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
- input_operands));
- fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+ fuzzerutil::AddGlobalVariable(
+ ir_context, message_.fresh_id(), message_.type_id(),
+ static_cast<SpvStorageClass>(message_.storage_class()),
+ message_.initializer_id());
- fuzzerutil::AddVariableIdToEntryPointInterfaces(ir_context,
- message_.fresh_id());
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
if (message_.value_is_irrelevant()) {
transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
diff --git a/source/fuzz/transformation_add_local_variable.cpp b/source/fuzz/transformation_add_local_variable.cpp
index 5136249..a93f104 100644
--- a/source/fuzz/transformation_add_local_variable.cpp
+++ b/source/fuzz/transformation_add_local_variable.cpp
@@ -70,18 +70,12 @@
void TransformationAddLocalVariable::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- fuzzerutil::FindFunction(ir_context, message_.function_id())
- ->begin()
- ->begin()
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
- opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_STORAGE_CLASS,
- {
+ fuzzerutil::AddLocalVariable(ir_context, message_.fresh_id(),
+ message_.type_id(), message_.function_id(),
+ message_.initializer_id());
- SpvStorageClassFunction}},
- {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}})));
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
if (message_.value_is_irrelevant()) {
transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
message_.fresh_id());
diff --git a/source/fuzz/transformation_push_id_through_variable.cpp b/source/fuzz/transformation_push_id_through_variable.cpp
index fb7946a..54d76fa 100644
--- a/source/fuzz/transformation_push_id_through_variable.cpp
+++ b/source/fuzz/transformation_push_id_through_variable.cpp
@@ -27,12 +27,13 @@
TransformationPushIdThroughVariable::TransformationPushIdThroughVariable(
uint32_t value_id, uint32_t value_synonym_id, uint32_t variable_id,
- uint32_t variable_storage_class,
+ uint32_t variable_storage_class, uint32_t initializer_id,
const protobufs::InstructionDescriptor& instruction_descriptor) {
message_.set_value_id(value_id);
message_.set_value_synonym_id(value_synonym_id);
message_.set_variable_id(variable_id);
message_.set_variable_storage_class(variable_storage_class);
+ message_.set_initializer_id(initializer_id);
*message_.mutable_instruction_descriptor() = instruction_descriptor;
}
@@ -85,6 +86,14 @@
message_.variable_storage_class() == SpvStorageClassFunction) &&
"The variable storage class must be private or function.");
+ // Check that initializer is valid.
+ const auto* constant_inst =
+ ir_context->get_def_use_mgr()->GetDef(message_.initializer_id());
+ if (!constant_inst || !spvOpcodeIsConstant(constant_inst->opcode()) ||
+ value_instruction->type_id() != constant_inst->type_id()) {
+ return false;
+ }
+
// |message_.value_id| must be available at the insertion point.
return fuzzerutil::IdIsAvailableBeforeInstruction(
ir_context, instruction_to_insert_before, message_.value_id());
@@ -103,28 +112,23 @@
assert(pointer_type_id && "The required pointer type must be available.");
// Adds whether a global or local variable.
- fuzzerutil::UpdateModuleIdBound(ir_context, message_.variable_id());
if (message_.variable_storage_class() == SpvStorageClassPrivate) {
- ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- ir_context, SpvOpVariable, pointer_type_id, message_.variable_id(),
- opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}}})));
-
- fuzzerutil::AddVariableIdToEntryPointInterfaces(ir_context,
- message_.variable_id());
+ fuzzerutil::AddGlobalVariable(ir_context, message_.variable_id(),
+ pointer_type_id, SpvStorageClassPrivate,
+ message_.initializer_id());
} else {
- ir_context
- ->get_instr_block(
- FindInstruction(message_.instruction_descriptor(), ir_context))
- ->GetParent()
- ->begin()
- ->begin()
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpVariable, pointer_type_id, message_.variable_id(),
- opt::Instruction::OperandList({{SPV_OPERAND_TYPE_STORAGE_CLASS,
- {SpvStorageClassFunction}}})));
+ auto function_id = ir_context
+ ->get_instr_block(FindInstruction(
+ message_.instruction_descriptor(), ir_context))
+ ->GetParent()
+ ->result_id();
+ fuzzerutil::AddLocalVariable(ir_context, message_.variable_id(),
+ pointer_type_id, function_id,
+ message_.initializer_id());
}
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.variable_id());
+
// Stores value id to variable id.
FindInstruction(message_.instruction_descriptor(), ir_context)
->InsertBefore(MakeUnique<opt::Instruction>(
diff --git a/source/fuzz/transformation_push_id_through_variable.h b/source/fuzz/transformation_push_id_through_variable.h
index e685ff8..24d3c2b 100644
--- a/source/fuzz/transformation_push_id_through_variable.h
+++ b/source/fuzz/transformation_push_id_through_variable.h
@@ -31,6 +31,7 @@
TransformationPushIdThroughVariable(
uint32_t value_id, uint32_t value_synonym_fresh_id,
uint32_t variable_fresh_id, uint32_t variable_storage_class,
+ uint32_t initializer_id,
const protobufs::InstructionDescriptor& instruction_descriptor);
// - |message_.value_id| must be an instruction result id that has the same
@@ -39,6 +40,9 @@
// - |message_.variable_id| must be fresh
// - |message_.variable_storage_class| must be either StorageClassPrivate or
// StorageClassFunction
+ // - |message_.initializer_id| must be a result id of some constant in the
+ // module. Its type must be equal to the pointee type of the variable that
+ // will be created.
// - |message_.instruction_descriptor| must identify an instruction
// which it is valid to insert the OpStore and OpLoad instructions before it
// and must be belongs to a reachable block.
diff --git a/test/fuzz/transformation_push_id_through_variable_test.cpp b/test/fuzz/transformation_push_id_through_variable_test.cpp
index f0bd3a6..8ba91bc 100644
--- a/test/fuzz/transformation_push_id_through_variable_test.cpp
+++ b/test/fuzz/transformation_push_id_through_variable_test.cpp
@@ -107,12 +107,13 @@
uint32_t value_id = 21;
uint32_t value_synonym_id = 62;
uint32_t variable_id = 63;
+ uint32_t initializer_id = 23;
uint32_t variable_storage_class = SpvStorageClassPrivate;
auto instruction_descriptor =
MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
auto transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -120,11 +121,12 @@
value_id = 80;
value_synonym_id = 60;
variable_id = 61;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -132,11 +134,12 @@
value_id = 80;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(64, SpvOpAccessChain, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -145,11 +148,12 @@
value_id = 24;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 24;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(27, SpvOpVariable, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -157,11 +161,12 @@
value_id = 80;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(100, SpvOpUnreachable, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -169,11 +174,12 @@
value_id = 64;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 23;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -181,11 +187,12 @@
value_id = 80;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassPrivate;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
@@ -193,11 +200,12 @@
value_id = 93;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 93;
variable_storage_class = SpvStorageClassInput;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
#ifndef NDEBUG
ASSERT_DEATH(
transformation.IsApplicable(context.get(), transformation_context),
@@ -208,11 +216,38 @@
value_id = 95;
value_synonym_id = 62;
variable_id = 63;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
+ ASSERT_FALSE(
+ transformation.IsApplicable(context.get(), transformation_context));
+
+ // Variable initializer is not constant.
+ value_id = 95;
+ value_synonym_id = 62;
+ variable_id = 63;
+ initializer_id = 95;
+ variable_storage_class = SpvStorageClassFunction;
+ instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+ transformation = TransformationPushIdThroughVariable(
+ value_id, value_synonym_id, variable_id, variable_storage_class,
+ initializer_id, instruction_descriptor);
+ ASSERT_FALSE(
+ transformation.IsApplicable(context.get(), transformation_context));
+
+ // Variable initializer has wrong type.
+ value_id = 95;
+ value_synonym_id = 62;
+ variable_id = 63;
+ initializer_id = 93;
+ variable_storage_class = SpvStorageClassFunction;
+ instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+ transformation = TransformationPushIdThroughVariable(
+ value_id, value_synonym_id, variable_id, variable_storage_class,
+ initializer_id, instruction_descriptor);
ASSERT_FALSE(
transformation.IsApplicable(context.get(), transformation_context));
}
@@ -298,52 +333,57 @@
uint32_t value_id = 80;
uint32_t value_synonym_id = 100;
uint32_t variable_id = 101;
+ uint32_t initializer_id = 80;
uint32_t variable_storage_class = SpvStorageClassFunction;
auto instruction_descriptor =
MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
auto transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
transformation.Apply(context.get(), &transformation_context);
value_id = 21;
value_synonym_id = 102;
variable_id = 103;
+ initializer_id = 21;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
transformation.Apply(context.get(), &transformation_context);
value_id = 95;
value_synonym_id = 104;
variable_id = 105;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
transformation.Apply(context.get(), &transformation_context);
value_id = 80;
value_synonym_id = 106;
variable_id = 107;
+ initializer_id = 80;
variable_storage_class = SpvStorageClassFunction;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
transformation.Apply(context.get(), &transformation_context);
value_id = 21;
value_synonym_id = 108;
variable_id = 109;
+ initializer_id = 21;
variable_storage_class = SpvStorageClassPrivate;
instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
- instruction_descriptor);
+ initializer_id, instruction_descriptor);
transformation.Apply(context.get(), &transformation_context);
std::string variant_shader = R"(
@@ -380,11 +420,11 @@
%91 = OpTypePointer Input %90
%92 = OpVariable %91 Input
%93 = OpConstantComposite %90 %24 %24 %24 %24
- %109 = OpVariable %51 Private
+ %109 = OpVariable %51 Private %21
%4 = OpFunction %2 None %3
%5 = OpLabel
- %103 = OpVariable %15 Function
- %101 = OpVariable %9 Function
+ %103 = OpVariable %15 Function %21
+ %101 = OpVariable %9 Function %80
%20 = OpVariable %9 Function
%27 = OpVariable %9 Function
%22 = OpAccessChain %15 %20 %14
@@ -413,8 +453,8 @@
%12 = OpFunction %6 None %10
%11 = OpFunctionParameter %9
%13 = OpLabel
- %107 = OpVariable %9 Function
- %105 = OpVariable %9 Function
+ %107 = OpVariable %9 Function %80
+ %105 = OpVariable %9 Function %80
%46 = OpCopyObject %9 %11
%16 = OpAccessChain %15 %11 %14
%95 = OpCopyObject %8 %80