[ir][spirv-writer] Implement user function calls
Bug: tint:1906 Change-Id: Icf9a0a00409b61d3c8baa844b66865c1a4dd9b69 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/134202 Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
c1fd6316de
commit
b54b58d57d
|
@ -25,6 +25,7 @@
|
|||
#include "src/tint/ir/module.h"
|
||||
#include "src/tint/ir/store.h"
|
||||
#include "src/tint/ir/transform/add_empty_entry_point.h"
|
||||
#include "src/tint/ir/user_call.h"
|
||||
#include "src/tint/ir/var.h"
|
||||
#include "src/tint/switch.h"
|
||||
#include "src/tint/transform/manager.h"
|
||||
|
@ -210,6 +211,7 @@ uint32_t GeneratorImplIr::Label(const ir::Block* block) {
|
|||
void GeneratorImplIr::EmitFunction(const ir::Function* func) {
|
||||
// Make an ID for the function.
|
||||
auto id = module_.NextId();
|
||||
functions_.Add(func->Name(), id);
|
||||
|
||||
// Emit the function name.
|
||||
module_.PushDebug(spv::Op::OpName, {id, Operand(func->Name().Name())});
|
||||
|
@ -319,6 +321,7 @@ void GeneratorImplIr::EmitBlock(const ir::Block* block) {
|
|||
EmitStore(s);
|
||||
return 0u;
|
||||
},
|
||||
[&](const ir::UserCall* c) { return EmitUserCall(c); },
|
||||
[&](const ir::Var* v) { return EmitVar(v); },
|
||||
[&](const ir::If* i) {
|
||||
EmitIf(i);
|
||||
|
@ -432,6 +435,16 @@ void GeneratorImplIr::EmitStore(const ir::Store* store) {
|
|||
current_function_.push_inst(spv::Op::OpStore, {Value(store->To()), Value(store->From())});
|
||||
}
|
||||
|
||||
uint32_t GeneratorImplIr::EmitUserCall(const ir::UserCall* call) {
|
||||
auto id = module_.NextId();
|
||||
OperandList operands = {Type(call->Type()), id, functions_.Get(call->Name()).value()};
|
||||
for (auto* arg : call->Args()) {
|
||||
operands.push_back(Value(arg));
|
||||
}
|
||||
current_function_.push_inst(spv::Op::OpFunctionCall, operands);
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t GeneratorImplIr::EmitVar(const ir::Var* var) {
|
||||
auto id = module_.NextId();
|
||||
auto* ptr = var->Type()->As<type::Pointer>();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "src/tint/constant/value.h"
|
||||
#include "src/tint/diagnostic/diagnostic.h"
|
||||
#include "src/tint/ir/constant.h"
|
||||
#include "src/tint/symbol.h"
|
||||
#include "src/tint/utils/hashmap.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
#include "src/tint/writer/spirv/binary_writer.h"
|
||||
|
@ -36,6 +37,7 @@ class Function;
|
|||
class Load;
|
||||
class Module;
|
||||
class Store;
|
||||
class UserCall;
|
||||
class Value;
|
||||
class Var;
|
||||
} // namespace tint::ir
|
||||
|
@ -117,6 +119,11 @@ class GeneratorImplIr {
|
|||
/// @param store the store instruction to emit
|
||||
void EmitStore(const ir::Store* store);
|
||||
|
||||
/// Emit a user call instruction.
|
||||
/// @param call the user call instruction to emit
|
||||
/// @returns the result ID of the instruction
|
||||
uint32_t EmitUserCall(const ir::UserCall* call);
|
||||
|
||||
/// Emit a var instruction.
|
||||
/// @param var the var instruction to emit
|
||||
/// @returns the result ID of the instruction
|
||||
|
@ -171,6 +178,10 @@ class GeneratorImplIr {
|
|||
/// The map of constants to their result IDs.
|
||||
utils::Hashmap<const constant::Value*, uint32_t, 16> constants_;
|
||||
|
||||
/// The map of functions to their result IDs.
|
||||
/// TODO(jrprice): Merge into `values_` map when `ir::Function` becomes an `ir::Value`.
|
||||
utils::Hashmap<Symbol, uint32_t, 8> functions_;
|
||||
|
||||
/// The map of non-constant values to their result IDs.
|
||||
utils::Hashmap<const ir::Value*, uint32_t, 8> values_;
|
||||
|
||||
|
|
|
@ -183,5 +183,73 @@ OpFunctionEnd
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(SpvGeneratorImplTest, Function_Call) {
|
||||
auto* i32_ty = mod.types.i32();
|
||||
auto* x = b.FunctionParam(i32_ty);
|
||||
auto* y = b.FunctionParam(i32_ty);
|
||||
auto* result = b.Add(i32_ty, x, y);
|
||||
auto* foo = b.CreateFunction("foo", i32_ty);
|
||||
foo->SetParams(utils::Vector{x, y});
|
||||
foo->StartTarget()->SetInstructions(
|
||||
utils::Vector{result, b.Branch(foo->EndTarget(), utils::Vector{result})});
|
||||
|
||||
auto* bar = b.CreateFunction("bar", mod.types.void_());
|
||||
bar->StartTarget()->SetInstructions(
|
||||
utils::Vector{b.UserCall(i32_ty, mod.symbols.Get("foo"),
|
||||
utils::Vector{b.Constant(i32(2)), b.Constant(i32(3))}),
|
||||
b.Branch(bar->EndTarget())});
|
||||
|
||||
generator_.EmitFunction(foo);
|
||||
generator_.EmitFunction(bar);
|
||||
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
|
||||
OpName %8 "bar"
|
||||
%2 = OpTypeInt 32 1
|
||||
%5 = OpTypeFunction %2 %2 %2
|
||||
%9 = OpTypeVoid
|
||||
%10 = OpTypeFunction %9
|
||||
%13 = OpConstant %2 2
|
||||
%14 = OpConstant %2 3
|
||||
%1 = OpFunction %2 None %5
|
||||
%3 = OpFunctionParameter %2
|
||||
%4 = OpFunctionParameter %2
|
||||
%6 = OpLabel
|
||||
%7 = OpIAdd %2 %3 %4
|
||||
OpReturnValue %7
|
||||
OpFunctionEnd
|
||||
%8 = OpFunction %9 None %10
|
||||
%11 = OpLabel
|
||||
%12 = OpFunctionCall %2 %1 %13 %14
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(SpvGeneratorImplTest, Function_Call_Void) {
|
||||
auto* foo = b.CreateFunction("foo", mod.types.void_());
|
||||
foo->StartTarget()->SetInstructions(utils::Vector{b.Branch(foo->EndTarget())});
|
||||
|
||||
auto* bar = b.CreateFunction("bar", mod.types.void_());
|
||||
bar->StartTarget()->SetInstructions(
|
||||
utils::Vector{b.UserCall(mod.types.void_(), mod.symbols.Get("foo"), utils::Empty),
|
||||
b.Branch(bar->EndTarget())});
|
||||
|
||||
generator_.EmitFunction(foo);
|
||||
generator_.EmitFunction(bar);
|
||||
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
|
||||
OpName %5 "bar"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%1 = OpFunction %2 None %3
|
||||
%4 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%5 = OpFunction %2 None %3
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %2 %1
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::writer::spirv
|
||||
|
|
Loading…
Reference in New Issue