[spirv-reader] Add Emit() and AddValue() helpers
This simplifies the mechanism for emitting instructions to the current
block and mapping SPIR-V result IDs to Tint IR values.
Add a test coverage for capturing the result of a function call, which
was not previously happening.
Bug: tint:1907
Change-Id: I1ca11b9eac3100e4cc7f513fafe5f0e33ec0ed74
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/168207
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/function_test.cc b/src/tint/lang/spirv/reader/parser/function_test.cc
index b9ec90a..a66b1e0 100644
--- a/src/tint/lang/spirv/reader/parser/function_test.cc
+++ b/src/tint/lang/spirv/reader/parser/function_test.cc
@@ -398,6 +398,56 @@
)");
}
+TEST_F(SpirvParserTest, FunctionCall_ReturnValueChain) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %fn_type = OpTypeFunction %bool
+ %main_type = OpTypeFunction %void
+
+ %bar = OpFunction %bool None %fn_type
+ %bar_start = OpLabel
+ OpReturnValue %true
+ OpFunctionEnd
+
+ %foo = OpFunction %bool None %fn_type
+ %foo_start = OpLabel
+ %call = OpFunctionCall %bool %foo
+ OpReturnValue %call
+ OpFunctionEnd
+
+ %main = OpFunction %void None %main_type
+ %main_start = OpLabel
+ %1 = OpFunctionCall %bool %bar
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+%1 = func():bool -> %b1 {
+ %b1 = block {
+ ret true
+ }
+}
+%2 = func():bool -> %b2 {
+ %b2 = block {
+ %3:bool = call %2
+ ret %3
+ }
+}
+%main = @compute @workgroup_size(1, 1, 1) func():void -> %b3 {
+ %b3 = block {
+ %5:bool = call %1
+ ret
+ }
+}
+)");
+}
+
TEST_F(SpirvParserTest, FunctionCall_ParamAndReturnValue) {
EXPECT_IR(R"(
OpCapability Shader
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index f9057b3..9541d10 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -76,7 +76,10 @@
return Failure("failed to build the internal representation of the module");
}
- EmitModuleScopeVariables();
+ {
+ TINT_SCOPED_ASSIGNMENT(current_block_, ir_.root_block);
+ EmitModuleScopeVariables();
+ }
EmitFunctions();
@@ -316,11 +319,27 @@
return nullptr;
}
+ /// Register an IR value for a SPIR-V result ID.
+ /// @param result_id the SPIR-V result ID
+ /// @param value the IR value
+ void AddValue(uint32_t result_id, core::ir::Value* value) { values_.Add(result_id, value); }
+
+ /// Emit an instruction to the current block.
+ /// @param inst the instruction to emit
+ /// @param result_id an optional SPIR-V result ID to register the instruction result for
+ void Emit(core::ir::Instruction* inst, uint32_t result_id = 0) {
+ current_block_->Append(inst);
+ if (result_id != 0) {
+ TINT_ASSERT_OR_RETURN(inst->Results().Length() == 1u);
+ AddValue(result_id, inst->Result(0));
+ }
+ }
+
/// Emit the module-scope variables.
void EmitModuleScopeVariables() {
for (auto& inst : spirv_context_->module()->types_values()) {
if (inst.opcode() == spv::Op::OpVariable) {
- ir_.root_block->Append(EmitVar(inst));
+ EmitVar(inst);
}
}
}
@@ -394,19 +413,20 @@
/// @param dst the Tint IR block to append to
/// @param src the SPIR-V block to emit
void EmitBlock(core::ir::Block* dst, const spvtools::opt::BasicBlock& src) {
+ TINT_SCOPED_ASSIGNMENT(current_block_, dst);
for (auto& inst : src) {
switch (inst.opcode()) {
case spv::Op::OpFunctionCall:
- dst->Append(EmitFunctionCall(inst));
+ EmitFunctionCall(inst);
break;
case spv::Op::OpReturn:
- dst->Append(b_.Return(current_function_));
+ Emit(b_.Return(current_function_));
break;
case spv::Op::OpReturnValue:
- dst->Append(b_.Return(current_function_, Value(inst.GetSingleWordOperand(0))));
+ Emit(b_.Return(current_function_, Value(inst.GetSingleWordOperand(0))));
break;
case spv::Op::OpVariable:
- dst->Append(EmitVar(inst));
+ EmitVar(inst);
break;
default:
TINT_UNIMPLEMENTED()
@@ -416,24 +436,22 @@
}
/// @param inst the SPIR-V instruction for OpFunctionCall
- /// @returns the Tint IR instruction
- core::ir::UserCall* EmitFunctionCall(const spvtools::opt::Instruction& inst) {
+ void EmitFunctionCall(const spvtools::opt::Instruction& inst) {
// TODO(crbug.com/tint/1907): Capture result.
Vector<core::ir::Value*, 4> args;
for (uint32_t i = 3; i < inst.NumOperandWords(); i++) {
args.Push(Value(inst.GetSingleWordOperand(i)));
}
- return b_.Call(Function(inst.GetSingleWordInOperand(0)), std::move(args));
+ Emit(b_.Call(Function(inst.GetSingleWordInOperand(0)), std::move(args)), inst.result_id());
}
/// @param inst the SPIR-V instruction for OpVariable
- /// @returns the Tint IR instruction
- core::ir::Var* EmitVar(const spvtools::opt::Instruction& inst) {
+ void EmitVar(const spvtools::opt::Instruction& inst) {
auto* var = b_.Var(Type(inst.type_id())->As<core::type::Pointer>());
if (inst.NumOperands() > 3) {
var->SetInitializer(Value(inst.GetSingleWordOperand(3)));
}
- return var;
+ Emit(var, inst.result_id());
}
private:
@@ -446,6 +464,8 @@
/// The Tint IR function that is currently being emitted.
core::ir::Function* current_function_ = nullptr;
+ /// The Tint IR block that is currently being emitted.
+ core::ir::Block* current_block_ = nullptr;
/// A map from a SPIR-V type declaration result ID to the corresponding Tint type object.
Hashmap<const spvtools::opt::analysis::Type*, const core::type::Type*, 16> types_;
/// A map from a SPIR-V function definition result ID to the corresponding Tint function object.