[ir][spirv-writer] Add support for parameters

Change the instruction->id map to a generic non-constant value->id map
so that it can be used for other types of values.

Bug: tint:1906
Change-Id: I79a0a7f671214167fa17ca903f9e94a54507d17c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/134201
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2023-05-24 14:03:16 +00:00 committed by Dawn LUCI CQ
parent f5a62539f4
commit 1ea7f0f351
3 changed files with 52 additions and 14 deletions

View File

@ -14,6 +14,8 @@
#include "src/tint/writer/spirv/ir/generator_impl_ir.h" #include "src/tint/writer/spirv/ir/generator_impl_ir.h"
#include <utility>
#include "spirv/unified1/spirv.h" #include "spirv/unified1/spirv.h"
#include "src/tint/ir/binary.h" #include "src/tint/ir/binary.h"
#include "src/tint/ir/block.h" #include "src/tint/ir/block.h"
@ -191,17 +193,13 @@ uint32_t GeneratorImplIr::Value(const ir::Value* value) {
return Switch( return Switch(
value, // value, //
[&](const ir::Constant* constant) { return Constant(constant); }, [&](const ir::Constant* constant) { return Constant(constant); },
[&](const ir::Instruction* inst) { [&](const ir::Value*) {
auto id = instructions_.Find(inst); auto id = values_.Find(value);
if (TINT_UNLIKELY(!id)) { if (TINT_UNLIKELY(!id)) {
TINT_ICE(Writer, diagnostics_) << "missing instruction result"; TINT_ICE(Writer, diagnostics_) << "missing result ID for value";
return 0u; return 0u;
} }
return *id; return *id;
},
[&](Default) {
TINT_ICE(Writer, diagnostics_) << "unhandled value node: " << value->TypeInfo().name;
return 0u;
}); });
} }
@ -224,9 +222,22 @@ void GeneratorImplIr::EmitFunction(const ir::Function* func) {
// Get the ID for the return type. // Get the ID for the return type.
auto return_type_id = Type(func->ReturnType()); auto return_type_id = Type(func->ReturnType());
// Get the ID for the function type (creating it if needed).
// TODO(jrprice): Add the parameter types when they are supported in the IR.
FunctionType function_type{return_type_id, {}}; FunctionType function_type{return_type_id, {}};
InstructionList params;
// Generate function parameter declarations and add their type IDs to the function signature.
for (auto* param : func->Params()) {
auto param_type_id = Type(param->Type());
auto param_id = module_.NextId();
params.push_back(Instruction(spv::Op::OpFunctionParameter, {param_type_id, param_id}));
values_.Add(param, param_id);
function_type.param_type_ids.Push(param_type_id);
if (auto name = ir_->NameOf(param)) {
module_.PushDebug(spv::Op::OpName, {param_id, Operand(name.Name())});
}
}
// Get the ID for the function type (creating it if needed).
auto function_type_id = function_types_.GetOrCreate(function_type, [&]() { auto function_type_id = function_types_.GetOrCreate(function_type, [&]() {
auto func_ty_id = module_.NextId(); auto func_ty_id = module_.NextId();
OperandList operands = {func_ty_id, return_type_id}; OperandList operands = {func_ty_id, return_type_id};
@ -242,9 +253,8 @@ void GeneratorImplIr::EmitFunction(const ir::Function* func) {
{return_type_id, id, U32Operand(SpvFunctionControlMaskNone), function_type_id}}; {return_type_id, id, U32Operand(SpvFunctionControlMaskNone), function_type_id}};
// Create a function that we will add instructions to. // Create a function that we will add instructions to.
// TODO(jrprice): Add the parameter declarations when they are supported in the IR.
auto entry_block = module_.NextId(); auto entry_block = module_.NextId();
current_function_ = Function(decl, entry_block, {}); current_function_ = Function(decl, entry_block, std::move(params));
TINT_DEFER(current_function_ = Function()); TINT_DEFER(current_function_ = Function());
// Emit the body of the function. // Emit the body of the function.
@ -323,7 +333,7 @@ void GeneratorImplIr::EmitBlock(const ir::Block* block) {
<< "unimplemented instruction: " << inst->TypeInfo().name; << "unimplemented instruction: " << inst->TypeInfo().name;
return 0u; return 0u;
}); });
instructions_.Add(inst, result); values_.Add(inst, result);
} }
} }

View File

@ -171,8 +171,8 @@ class GeneratorImplIr {
/// The map of constants to their result IDs. /// The map of constants to their result IDs.
utils::Hashmap<const constant::Value*, uint32_t, 16> constants_; utils::Hashmap<const constant::Value*, uint32_t, 16> constants_;
/// The map of instructions to their result IDs. /// The map of non-constant values to their result IDs.
utils::Hashmap<const ir::Instruction*, uint32_t, 8> instructions_; utils::Hashmap<const ir::Value*, uint32_t, 8> values_;
/// The map of blocks to the IDs of their label instructions. /// The map of blocks to the IDs of their label instructions.
utils::Hashmap<const ir::Block*, uint32_t, 8> block_labels_; utils::Hashmap<const ir::Block*, uint32_t, 8> block_labels_;

View File

@ -155,5 +155,33 @@ OpFunctionEnd
)"); )");
} }
TEST_F(SpvGeneratorImplTest, Function_Parameters) {
auto* i32 = mod.types.i32();
auto* x = b.FunctionParam(i32);
auto* y = b.FunctionParam(i32);
auto* result = b.Add(i32, x, y);
auto* func = b.CreateFunction("foo", i32);
func->SetParams(utils::Vector{x, y});
func->StartTarget()->SetInstructions(
utils::Vector{result, b.Branch(func->EndTarget(), utils::Vector{result})});
mod.SetName(x, "x");
mod.SetName(y, "y");
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
OpName %3 "x"
OpName %4 "y"
%2 = OpTypeInt 32 1
%5 = OpTypeFunction %2 %2 %2
%1 = OpFunction %2 None %5
%3 = OpFunctionParameter %2
%4 = OpFunctionParameter %2
%6 = OpLabel
%7 = OpIAdd %2 %3 %4
OpReturnValue %7
OpFunctionEnd
)");
}
} // namespace } // namespace
} // namespace tint::writer::spirv } // namespace tint::writer::spirv