diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index 38fe7c17cf..4ea36bb5c2 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -699,8 +699,14 @@ if(${TINT_BUILD_IR}) ir/builder.h ir/builder_impl.cc ir/builder_impl.h + ir/call.cc + ir/call.h ir/constant.cc ir/constant.h + ir/construct.cc + ir/construct.h + ir/convert.cc + ir/convert.h ir/debug.cc ir/debug.h ir/disassembler.cc @@ -723,6 +729,8 @@ if(${TINT_BUILD_IR}) ir/temp.h ir/terminator.cc ir/terminator.h + ir/user_call.cc + ir/user_call.h ir/value.cc ir/value.h ) diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc index 1452dc4e03..96578c5415 100644 --- a/src/tint/ir/builder.cc +++ b/src/tint/ir/builder.cc @@ -177,4 +177,20 @@ ir::Bitcast* Builder::Bitcast(const type::Type* type, Value* val) { return ir.instructions.Create(Temp(type), val); } +ir::UserCall* Builder::UserCall(const type::Type* type, + Symbol name, + utils::VectorRef args) { + return ir.instructions.Create(Temp(type), name, std::move(args)); +} + +ir::Convert* Builder::Convert(const type::Type* to, + const type::Type* from, + utils::VectorRef args) { + return ir.instructions.Create(Temp(to), from, std::move(args)); +} + +ir::Construct* Builder::Construct(const type::Type* to, utils::VectorRef args) { + return ir.instructions.Create(Temp(to), std::move(args)); +} + } // namespace tint::ir diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h index 147e4c4fcd..e7d64bb1ce 100644 --- a/src/tint/ir/builder.h +++ b/src/tint/ir/builder.h @@ -21,6 +21,8 @@ #include "src/tint/ir/binary.h" #include "src/tint/ir/bitcast.h" #include "src/tint/ir/constant.h" +#include "src/tint/ir/construct.h" +#include "src/tint/ir/convert.h" #include "src/tint/ir/function.h" #include "src/tint/ir/if.h" #include "src/tint/ir/loop.h" @@ -28,6 +30,7 @@ #include "src/tint/ir/switch.h" #include "src/tint/ir/temp.h" #include "src/tint/ir/terminator.h" +#include "src/tint/ir/user_call.h" #include "src/tint/ir/value.h" #include "src/tint/type/bool.h" #include "src/tint/type/f16.h" @@ -279,6 +282,28 @@ class Builder { /// @returns the instruction ir::Bitcast* Bitcast(const type::Type* type, Value* val); + /// Creates a user function call instruction + /// @param type the return type of the call + /// @param name the name of the function being called + /// @param args the call arguments + /// @returns the instruction + ir::UserCall* UserCall(const type::Type* type, Symbol name, utils::VectorRef args); + + /// Creates a value conversion instruction + /// @param to the type converted to + /// @param from the type converted from + /// @param args the arguments to be converted + /// @returns the instruction + ir::Convert* Convert(const type::Type* to, + const type::Type* from, + utils::VectorRef args); + + /// Creates a value constructor instruction + /// @param to the type being converted + /// @param args the arguments to be converted + /// @returns the instruction + ir::Construct* Construct(const type::Type* to, utils::VectorRef args); + /// @returns a unique temp id Temp::Id AllocateTempId(); diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc index d3f8d53037..e77396672a 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -14,6 +14,8 @@ #include "src/tint/ir/builder_impl.h" +#include + #include "src/tint/ast/alias.h" #include "src/tint/ast/binary_expression.h" #include "src/tint/ast/bitcast_expression.h" @@ -21,6 +23,8 @@ #include "src/tint/ast/bool_literal_expression.h" #include "src/tint/ast/break_if_statement.h" #include "src/tint/ast/break_statement.h" +#include "src/tint/ast/call_expression.h" +#include "src/tint/ast/call_statement.h" #include "src/tint/ast/const_assert.h" #include "src/tint/ast/continue_statement.h" #include "src/tint/ast/float_literal_expression.h" @@ -28,6 +32,7 @@ #include "src/tint/ast/function.h" #include "src/tint/ast/id_attribute.h" #include "src/tint/ast/identifier.h" +#include "src/tint/ast/identifier_expression.h" #include "src/tint/ast/if_statement.h" #include "src/tint/ast/int_literal_expression.h" #include "src/tint/ast/literal_expression.h" @@ -39,6 +44,7 @@ #include "src/tint/ast/struct_member_align_attribute.h" #include "src/tint/ast/struct_member_size_attribute.h" #include "src/tint/ast/switch_statement.h" +#include "src/tint/ast/templated_identifier.h" #include "src/tint/ast/variable_decl_statement.h" #include "src/tint/ast/while_statement.h" #include "src/tint/ir/function.h" @@ -48,8 +54,12 @@ #include "src/tint/ir/switch.h" #include "src/tint/ir/terminator.h" #include "src/tint/program.h" +#include "src/tint/sem/builtin.h" +#include "src/tint/sem/call.h" #include "src/tint/sem/module.h" #include "src/tint/sem/switch_statement.h" +#include "src/tint/sem/value_constructor.h" +#include "src/tint/sem/value_conversion.h" #include "src/tint/sem/value_expression.h" #include "src/tint/type/void.h" @@ -237,9 +247,7 @@ bool BuilderImpl::EmitStatement(const ast::Statement* stmt) { [&](const ast::BlockStatement* b) { return EmitBlock(b); }, [&](const ast::BreakStatement* b) { return EmitBreak(b); }, [&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); }, - // [&](const ast::CallStatement* c) { - // TODO(dsinclair): Implement - // }, + [&](const ast::CallStatement* c) { return EmitCall(c); }, // [&](const ast::CompoundAssignmentStatement* c) { // TODO(dsinclair): Implement // }, @@ -593,9 +601,7 @@ utils::Result BuilderImpl::EmitExpression(const ast::Expression* expr) { // }, [&](const ast::BinaryExpression* b) { return EmitBinary(b); }, [&](const ast::BitcastExpression* b) { return EmitBitcast(b); }, - // [&](const ast::CallExpression* c) { - // TODO(dsinclair): Implement - // }, + [&](const ast::CallExpression* c) { return EmitCall(c); }, // [&](const ast::IdentifierExpression* i) { // TODO(dsinclair): Implement // }, @@ -743,6 +749,63 @@ utils::Result BuilderImpl::EmitBitcast(const ast::BitcastExpression* exp return instr->Result(); } +utils::Result BuilderImpl::EmitCall(const ast::CallStatement* stmt) { + return EmitCall(stmt->expr); +} + +utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { + utils::Vector args; + args.Reserve(expr->args.Length()); + + // Emit the arguments + for (const auto* arg : expr->args) { + auto value = EmitExpression(arg); + if (!value) { + diagnostics_.add_error(tint::diag::System::IR, "Failed to convert arguments", + arg->source); + return utils::Failure; + } + args.Push(value.Get()); + } + + auto* sem = program_->Sem().Get(expr); + if (!sem) { + diagnostics_.add_error( + tint::diag::System::IR, + "Failed to get semantic information for call " + std::string(expr->TypeInfo().name), + expr->source); + return utils::Failure; + } + + auto* ty = sem->Target()->ReturnType()->Clone(clone_ctx_.type_ctx); + + Instruction* instr = nullptr; + + // If this is a builtin function, emit the specific builtin value + if (sem->Target()->As()) { + // TODO(dsinclair): .. something ... + diagnostics_.add_error(tint::diag::System::IR, "Missing builtin function support", + expr->source); + } else if (sem->Target()->As()) { + instr = builder.Construct(ty, std::move(args)); + } else if (auto* conv = sem->Target()->As()) { + auto* from = conv->Source()->Clone(clone_ctx_.type_ctx); + instr = builder.Convert(ty, from, std::move(args)); + } else if (expr->target->identifier->Is()) { + TINT_UNIMPLEMENTED(IR, diagnostics_) << "Missing templated ident support"; + return utils::Failure; + } else { + // Not a builtin and not a templated call, so this is a user function. + auto name = CloneSymbol(expr->target->identifier->symbol); + instr = builder.UserCall(ty, name, std::move(args)); + } + if (instr == nullptr) { + return utils::Failure; + } + current_flow_block->instructions.Push(instr); + return instr->Result(); +} + utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) { auto* sem = program_->Sem().Get(lit); if (!sem) { diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h index 034ab65c4d..e531aedcf3 100644 --- a/src/tint/ir/builder_impl.h +++ b/src/tint/ir/builder_impl.h @@ -39,6 +39,8 @@ class BitcastExpression; class BlockStatement; class BreakIfStatement; class BreakStatement; +class CallExpression; +class CallStatement; class ContinueStatement; class Expression; class ForLoopStatement; @@ -61,6 +63,9 @@ class Loop; class Switch; class Terminator; } // namespace tint::ir +namespace tint::sem { +class Builtin; +} // namespace tint::sem namespace tint::ir { @@ -165,6 +170,16 @@ class BuilderImpl { /// @returns the value storing the result if successful, utils::Failure otherwise utils::Result EmitBitcast(const ast::BitcastExpression* expr); + /// Emits a call expression + /// @param stmt the call statement + /// @returns the value storing the result if successful, utils::Failure otherwise + utils::Result EmitCall(const ast::CallStatement* stmt); + + /// Emits a call expression + /// @param expr the call expression + /// @returns the value storing the result if successful, utils::Failure otherwise + utils::Result EmitCall(const ast::CallExpression* expr); + /// Emits a literal expression /// @param lit the literal to emit /// @returns true if successful, false otherwise diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 9af481b806..be94e653e0 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -1858,5 +1858,70 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) { )"); } +TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) { + Func("my_func", utils::Vector{Param("p", ty.f32())}, ty.void_(), utils::Empty); + + auto* stmt = CallStmt(Call("my_func", Mul(2_f, 3_f))); + WrapInFunction(stmt); + + auto& b = CreateBuilder(); + InjectFlowBlock(); + auto r = b.EmitStatement(stmt); + ASSERT_TRUE(r) << b.error(); + + Disassembler d(b.builder.ir); + d.EmitBlockInstructions(b.current_flow_block->As()); + EXPECT_EQ(d.AsString(), R"(%1 (f32) = 2.0 * 3.0 +%2 (void) = call(my_func, %1 (f32)) +)"); +} + +TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) { + auto* expr = vec3(ty.f32()); + WrapInFunction(expr); + + auto& b = CreateBuilder(); + InjectFlowBlock(); + auto r = b.EmitExpression(expr); + ASSERT_TRUE(r) << b.error(); + + Disassembler d(b.builder.ir); + d.EmitBlockInstructions(b.current_flow_block->As()); + EXPECT_EQ(d.AsString(), R"(%1 (vec3) = construct(vec3) +)"); +} + +TEST_F(IR_BuilderImplTest, EmitExpression_Construct) { + auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f)); + auto* expr = vec3(ty.f32(), 2_f, 3_f, i); + WrapInFunction(expr); + + auto& b = CreateBuilder(); + InjectFlowBlock(); + auto r = b.EmitExpression(expr); + ASSERT_TRUE(r) << b.error(); + + Disassembler d(b.builder.ir); + d.EmitBlockInstructions(b.current_flow_block->As()); + EXPECT_EQ(d.AsString(), R"(%2 (vec3) = construct(vec3, 2.0, 3.0, %1 (void)) +)"); +} + +TEST_F(IR_BuilderImplTest, EmitExpression_Convert) { + auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i)); + auto* expr = Call(ty.f32(), i); + WrapInFunction(expr); + + auto& b = CreateBuilder(); + InjectFlowBlock(); + auto r = b.EmitExpression(expr); + ASSERT_TRUE(r) << b.error(); + + Disassembler d(b.builder.ir); + d.EmitBlockInstructions(b.current_flow_block->As()); + EXPECT_EQ(d.AsString(), R"(%2 (f32) = convert(f32, i32, %1 (void)) +)"); +} + } // namespace } // namespace tint::ir diff --git a/src/tint/ir/call.cc b/src/tint/ir/call.cc new file mode 100644 index 0000000000..9dda1f9fb1 --- /dev/null +++ b/src/tint/ir/call.cc @@ -0,0 +1,40 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/ir/call.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::Call); + +namespace tint::ir { + +Call::Call(Value* result, utils::VectorRef args) : Base(result), args_(args) { + for (auto* arg : args) { + arg->AddUsage(this); + } +} + +Call::~Call() = default; + +void Call::EmitArgs(utils::StringStream& out, const SymbolTable& st) const { + bool first = true; + for (const auto* arg : args_) { + if (!first) { + out << ", "; + } + first = false; + arg->ToString(out, st); + } +} + +} // namespace tint::ir diff --git a/src/tint/ir/call.h b/src/tint/ir/call.h new file mode 100644 index 0000000000..d6ced3f069 --- /dev/null +++ b/src/tint/ir/call.h @@ -0,0 +1,54 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_IR_CALL_H_ +#define SRC_TINT_IR_CALL_H_ + +#include "src/tint/castable.h" +#include "src/tint/ir/instruction.h" +#include "src/tint/symbol_table.h" +#include "src/tint/type/type.h" +#include "src/tint/utils/string_stream.h" + +namespace tint::ir { + +/// A Call instruction in the IR. +class Call : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param args the constructor arguments + Call(Value* result, utils::VectorRef args); + Call(const Call& instr) = delete; + Call(Call&& instr) = delete; + ~Call() override; + + Call& operator=(const Call& instr) = delete; + Call& operator=(Call&& instr) = delete; + + /// @returns the constructor arguments + utils::VectorRef Args() const { return args_; } + + /// Writes the call arguments to the given stream. + /// @param out the output stream + /// @param st the symbol table + void EmitArgs(utils::StringStream& out, const SymbolTable& st) const; + + private: + utils::Vector args_; +}; + +} // namespace tint::ir + +#endif // SRC_TINT_IR_CALL_H_ diff --git a/src/tint/ir/construct.cc b/src/tint/ir/construct.cc new file mode 100644 index 0000000000..27bb084d19 --- /dev/null +++ b/src/tint/ir/construct.cc @@ -0,0 +1,37 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/ir/construct.h" +#include "src/tint/debug.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::Construct); + +namespace tint::ir { + +Construct::Construct(Value* result, utils::VectorRef args) : Base(result, args) {} + +Construct::~Construct() = default; + +utils::StringStream& Construct::ToString(utils::StringStream& out, const SymbolTable& st) const { + Result()->ToString(out, st); + out << " = construct(" << Result()->Type()->FriendlyName(st); + if (!Args().IsEmpty()) { + out << ", "; + EmitArgs(out, st); + } + out << ")"; + return out; +} + +} // namespace tint::ir diff --git a/src/tint/ir/construct.h b/src/tint/ir/construct.h new file mode 100644 index 0000000000..6f620d3e6a --- /dev/null +++ b/src/tint/ir/construct.h @@ -0,0 +1,49 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_IR_CONSTRUCT_H_ +#define SRC_TINT_IR_CONSTRUCT_H_ + +#include "src/tint/castable.h" +#include "src/tint/ir/call.h" +#include "src/tint/symbol_table.h" +#include "src/tint/type/type.h" +#include "src/tint/utils/string_stream.h" + +namespace tint::ir { + +/// A constructor instruction in the IR. +class Construct : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param args the constructor arguments + Construct(Value* result, utils::VectorRef args); + Construct(const Construct& instr) = delete; + Construct(Construct&& instr) = delete; + ~Construct() override; + + Construct& operator=(const Construct& instr) = delete; + Construct& operator=(Construct&& instr) = delete; + + /// Write the instruction to the given stream + /// @param out the stream to write to + /// @param st the symbol table + /// @returns the stream + utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override; +}; + +} // namespace tint::ir + +#endif // SRC_TINT_IR_CONSTRUCT_H_ diff --git a/src/tint/ir/convert.cc b/src/tint/ir/convert.cc new file mode 100644 index 0000000000..e845adb6e1 --- /dev/null +++ b/src/tint/ir/convert.cc @@ -0,0 +1,36 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/ir/convert.h" +#include "src/tint/debug.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::Convert); + +namespace tint::ir { + +Convert::Convert(Value* result, const type::Type* from, utils::VectorRef args) + : Base(result, args), from_(from) {} + +Convert::~Convert() = default; + +utils::StringStream& Convert::ToString(utils::StringStream& out, const SymbolTable& st) const { + Result()->ToString(out, st); + out << " = convert(" << Result()->Type()->FriendlyName(st) << ", " << from_->FriendlyName(st) + << ", "; + EmitArgs(out, st); + out << ")"; + return out; +} + +} // namespace tint::ir diff --git a/src/tint/ir/convert.h b/src/tint/ir/convert.h new file mode 100644 index 0000000000..5132248ba6 --- /dev/null +++ b/src/tint/ir/convert.h @@ -0,0 +1,58 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_IR_CONVERT_H_ +#define SRC_TINT_IR_CONVERT_H_ + +#include "src/tint/castable.h" +#include "src/tint/ir/call.h" +#include "src/tint/symbol_table.h" +#include "src/tint/type/type.h" +#include "src/tint/utils/string_stream.h" + +namespace tint::ir { + +/// A value conversion instruction in the IR. +class Convert : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param from the type being converted from + /// @param args the conversion arguments + Convert(Value* result, const type::Type* from, utils::VectorRef args); + Convert(const Convert& instr) = delete; + Convert(Convert&& instr) = delete; + ~Convert() override; + + Convert& operator=(const Convert& instr) = delete; + Convert& operator=(Convert&& instr) = delete; + + /// @returns the from type + const type::Type* From() const { return from_; } + /// @returns the to type + const type::Type* To() const { return Result()->Type(); } + + /// Write the instruction to the given stream + /// @param out the stream to write to + /// @param st the symbol table + /// @returns the stream + utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override; + + private: + const type::Type* from_ = nullptr; +}; + +} // namespace tint::ir + +#endif // SRC_TINT_IR_CONVERT_H_ diff --git a/src/tint/ir/test_helper.h b/src/tint/ir/test_helper.h index 9fb54cc38c..6e36ed3390 100644 --- a/src/tint/ir/test_helper.h +++ b/src/tint/ir/test_helper.h @@ -40,6 +40,8 @@ class TestHelperBase : public BASE, public ProgramBuilder { /// return the same builder without rebuilding. /// @return the builder BuilderImpl& CreateBuilder() { + SetResolveOnBuild(true); + if (gen_) { return *gen_; } diff --git a/src/tint/ir/user_call.cc b/src/tint/ir/user_call.cc new file mode 100644 index 0000000000..cf672cf8d8 --- /dev/null +++ b/src/tint/ir/user_call.cc @@ -0,0 +1,36 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/ir/user_call.h" +#include "src/tint/debug.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::UserCall); + +namespace tint::ir { + +UserCall::UserCall(Value* result, Symbol name, utils::VectorRef args) + : Base(result, args), name_(name) {} + +UserCall::~UserCall() = default; + +utils::StringStream& UserCall::ToString(utils::StringStream& out, const SymbolTable& st) const { + Result()->ToString(out, st); + out << " = call("; + out << st.NameFor(name_) << ", "; + EmitArgs(out, st); + out << ")"; + return out; +} + +} // namespace tint::ir diff --git a/src/tint/ir/user_call.h b/src/tint/ir/user_call.h new file mode 100644 index 0000000000..2edeecb6d5 --- /dev/null +++ b/src/tint/ir/user_call.h @@ -0,0 +1,56 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_IR_USER_CALL_H_ +#define SRC_TINT_IR_USER_CALL_H_ + +#include "src/tint/castable.h" +#include "src/tint/ir/call.h" +#include "src/tint/symbol_table.h" +#include "src/tint/type/type.h" +#include "src/tint/utils/string_stream.h" + +namespace tint::ir { + +/// A user call instruction in the IR. +class UserCall : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param name the function name + /// @param args the function arguments + UserCall(Value* result, Symbol name, utils::VectorRef args); + UserCall(const UserCall& instr) = delete; + UserCall(UserCall&& instr) = delete; + ~UserCall() override; + + UserCall& operator=(const UserCall& instr) = delete; + UserCall& operator=(UserCall&& instr) = delete; + + /// @returns the function name + Symbol Name() const { return name_; } + + /// Write the instruction to the given stream + /// @param out the stream to write to + /// @param st the symbol table + /// @returns the stream + utils::StringStream& ToString(utils::StringStream& out, const SymbolTable& st) const override; + + private: + Symbol name_{}; +}; + +} // namespace tint::ir + +#endif // SRC_TINT_IR_USER_CALL_H_