diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index db51dfbaa0..0f442ff720 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -703,6 +703,8 @@ if(${TINT_BUILD_IR}) ir/builder.h ir/builder_impl.cc ir/builder_impl.h + ir/builtin.cc + ir/builtin.h ir/call.cc ir/call.h ir/constant.cc diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc index 96578c5415..a3d2a31617 100644 --- a/src/tint/ir/builder.cc +++ b/src/tint/ir/builder.cc @@ -193,4 +193,10 @@ ir::Construct* Builder::Construct(const type::Type* to, utils::VectorRef return ir.instructions.Create(Temp(to), std::move(args)); } +ir::Builtin* Builder::Builtin(const type::Type* type, + builtin::Function func, + utils::VectorRef args) { + return ir.instructions.Create(Temp(type), func, args); +} + } // namespace tint::ir diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h index e7d64bb1ce..5a39dbb6af 100644 --- a/src/tint/ir/builder.h +++ b/src/tint/ir/builder.h @@ -20,6 +20,7 @@ #include "src/tint/constant/scalar.h" #include "src/tint/ir/binary.h" #include "src/tint/ir/bitcast.h" +#include "src/tint/ir/builtin.h" #include "src/tint/ir/constant.h" #include "src/tint/ir/construct.h" #include "src/tint/ir/convert.h" @@ -304,6 +305,15 @@ class Builder { /// @returns the instruction ir::Construct* Construct(const type::Type* to, utils::VectorRef args); + /// Creates a builtin call instruction + /// @param type the return type + /// @param func the builtin function + /// @param args the arguments to be converted + /// @returns the instruction + ir::Builtin* Builtin(const type::Type* type, + builtin::Function func, + 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 02a7291809..ba63be6adb 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -791,9 +791,8 @@ utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { Instruction* instr = nullptr; // If this is a builtin function, emit the specific builtin value - if (sem->Target()->As()) { - // TODO(dsinclair): .. something ... - add_error(expr->source, "missing builtin function support"); + if (auto* b = sem->Target()->As()) { + instr = builder.Builtin(ty, b->Type(), args); } else if (sem->Target()->As()) { instr = builder.Construct(ty, std::move(args)); } else if (auto* conv = sem->Target()->As()) { diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 1705084a05..4e02875f71 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -1943,5 +1943,21 @@ FunctionEnd )"); } +TEST_F(IR_BuilderImplTest, EmitExpression_Builtin) { + auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f)); + auto* expr = Call("asin", 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) = asin(%1 (void)) +)"); +} + } // namespace } // namespace tint::ir diff --git a/src/tint/ir/builtin.cc b/src/tint/ir/builtin.cc new file mode 100644 index 0000000000..e9acf66394 --- /dev/null +++ b/src/tint/ir/builtin.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/builtin.h" +#include "src/tint/debug.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::Builtin); + +// \cond DO_NOT_DOCUMENT +namespace tint::ir { + +Builtin::Builtin(Value* result, builtin::Function func, utils::VectorRef args) + : Base(result, args), func_(func) {} + +Builtin::~Builtin() = default; + +utils::StringStream& Builtin::ToString(utils::StringStream& out, const SymbolTable& st) const { + Result()->ToString(out, st); + out << " = " << builtin::str(func_) << "("; + EmitArgs(out, st); + out << ")"; + return out; +} + +} // namespace tint::ir +// \endcond diff --git a/src/tint/ir/builtin.h b/src/tint/ir/builtin.h new file mode 100644 index 0000000000..0385c6cb7f --- /dev/null +++ b/src/tint/ir/builtin.h @@ -0,0 +1,57 @@ +// 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_BUILTIN_H_ +#define SRC_TINT_IR_BUILTIN_H_ + +#include "src/tint/builtin/function.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 Builtin : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param func the builtin function + /// @param args the conversion arguments + Builtin(Value* result, builtin::Function func, utils::VectorRef args); + Builtin(const Builtin& instr) = delete; + Builtin(Builtin&& instr) = delete; + ~Builtin() override; + + Builtin& operator=(const Builtin& instr) = delete; + Builtin& operator=(Builtin&& instr) = delete; + + /// @returns the builtin function + builtin::Function Func() const { return func_; } + + /// 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 builtin::Function func_; +}; + +} // namespace tint::ir + +#endif // SRC_TINT_IR_BUILTIN_H_