[ir] Add user functions, value constructors and value converters
This CL adds user function calls, value constructors and value converters into the IR. Bug: tint:1718 Change-Id: Iab59aa7d01b9d7831299d785f6e45e9fba12f7b5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122600 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
51be3420b8
commit
724a70f7a1
|
@ -699,8 +699,14 @@ if(${TINT_BUILD_IR})
|
||||||
ir/builder.h
|
ir/builder.h
|
||||||
ir/builder_impl.cc
|
ir/builder_impl.cc
|
||||||
ir/builder_impl.h
|
ir/builder_impl.h
|
||||||
|
ir/call.cc
|
||||||
|
ir/call.h
|
||||||
ir/constant.cc
|
ir/constant.cc
|
||||||
ir/constant.h
|
ir/constant.h
|
||||||
|
ir/construct.cc
|
||||||
|
ir/construct.h
|
||||||
|
ir/convert.cc
|
||||||
|
ir/convert.h
|
||||||
ir/debug.cc
|
ir/debug.cc
|
||||||
ir/debug.h
|
ir/debug.h
|
||||||
ir/disassembler.cc
|
ir/disassembler.cc
|
||||||
|
@ -723,6 +729,8 @@ if(${TINT_BUILD_IR})
|
||||||
ir/temp.h
|
ir/temp.h
|
||||||
ir/terminator.cc
|
ir/terminator.cc
|
||||||
ir/terminator.h
|
ir/terminator.h
|
||||||
|
ir/user_call.cc
|
||||||
|
ir/user_call.h
|
||||||
ir/value.cc
|
ir/value.cc
|
||||||
ir/value.h
|
ir/value.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -177,4 +177,20 @@ ir::Bitcast* Builder::Bitcast(const type::Type* type, Value* val) {
|
||||||
return ir.instructions.Create<ir::Bitcast>(Temp(type), val);
|
return ir.instructions.Create<ir::Bitcast>(Temp(type), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ir::UserCall* Builder::UserCall(const type::Type* type,
|
||||||
|
Symbol name,
|
||||||
|
utils::VectorRef<Value*> args) {
|
||||||
|
return ir.instructions.Create<ir::UserCall>(Temp(type), name, std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
ir::Convert* Builder::Convert(const type::Type* to,
|
||||||
|
const type::Type* from,
|
||||||
|
utils::VectorRef<Value*> args) {
|
||||||
|
return ir.instructions.Create<ir::Convert>(Temp(to), from, std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
ir::Construct* Builder::Construct(const type::Type* to, utils::VectorRef<Value*> args) {
|
||||||
|
return ir.instructions.Create<ir::Construct>(Temp(to), std::move(args));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tint::ir
|
} // namespace tint::ir
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "src/tint/ir/binary.h"
|
#include "src/tint/ir/binary.h"
|
||||||
#include "src/tint/ir/bitcast.h"
|
#include "src/tint/ir/bitcast.h"
|
||||||
#include "src/tint/ir/constant.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/function.h"
|
||||||
#include "src/tint/ir/if.h"
|
#include "src/tint/ir/if.h"
|
||||||
#include "src/tint/ir/loop.h"
|
#include "src/tint/ir/loop.h"
|
||||||
|
@ -28,6 +30,7 @@
|
||||||
#include "src/tint/ir/switch.h"
|
#include "src/tint/ir/switch.h"
|
||||||
#include "src/tint/ir/temp.h"
|
#include "src/tint/ir/temp.h"
|
||||||
#include "src/tint/ir/terminator.h"
|
#include "src/tint/ir/terminator.h"
|
||||||
|
#include "src/tint/ir/user_call.h"
|
||||||
#include "src/tint/ir/value.h"
|
#include "src/tint/ir/value.h"
|
||||||
#include "src/tint/type/bool.h"
|
#include "src/tint/type/bool.h"
|
||||||
#include "src/tint/type/f16.h"
|
#include "src/tint/type/f16.h"
|
||||||
|
@ -279,6 +282,28 @@ class Builder {
|
||||||
/// @returns the instruction
|
/// @returns the instruction
|
||||||
ir::Bitcast* Bitcast(const type::Type* type, Value* val);
|
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<Value*> 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<Value*> 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<Value*> args);
|
||||||
|
|
||||||
/// @returns a unique temp id
|
/// @returns a unique temp id
|
||||||
Temp::Id AllocateTempId();
|
Temp::Id AllocateTempId();
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "src/tint/ir/builder_impl.h"
|
#include "src/tint/ir/builder_impl.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "src/tint/ast/alias.h"
|
#include "src/tint/ast/alias.h"
|
||||||
#include "src/tint/ast/binary_expression.h"
|
#include "src/tint/ast/binary_expression.h"
|
||||||
#include "src/tint/ast/bitcast_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/bool_literal_expression.h"
|
||||||
#include "src/tint/ast/break_if_statement.h"
|
#include "src/tint/ast/break_if_statement.h"
|
||||||
#include "src/tint/ast/break_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/const_assert.h"
|
||||||
#include "src/tint/ast/continue_statement.h"
|
#include "src/tint/ast/continue_statement.h"
|
||||||
#include "src/tint/ast/float_literal_expression.h"
|
#include "src/tint/ast/float_literal_expression.h"
|
||||||
|
@ -28,6 +32,7 @@
|
||||||
#include "src/tint/ast/function.h"
|
#include "src/tint/ast/function.h"
|
||||||
#include "src/tint/ast/id_attribute.h"
|
#include "src/tint/ast/id_attribute.h"
|
||||||
#include "src/tint/ast/identifier.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/if_statement.h"
|
||||||
#include "src/tint/ast/int_literal_expression.h"
|
#include "src/tint/ast/int_literal_expression.h"
|
||||||
#include "src/tint/ast/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_align_attribute.h"
|
||||||
#include "src/tint/ast/struct_member_size_attribute.h"
|
#include "src/tint/ast/struct_member_size_attribute.h"
|
||||||
#include "src/tint/ast/switch_statement.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/variable_decl_statement.h"
|
||||||
#include "src/tint/ast/while_statement.h"
|
#include "src/tint/ast/while_statement.h"
|
||||||
#include "src/tint/ir/function.h"
|
#include "src/tint/ir/function.h"
|
||||||
|
@ -48,8 +54,12 @@
|
||||||
#include "src/tint/ir/switch.h"
|
#include "src/tint/ir/switch.h"
|
||||||
#include "src/tint/ir/terminator.h"
|
#include "src/tint/ir/terminator.h"
|
||||||
#include "src/tint/program.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/module.h"
|
||||||
#include "src/tint/sem/switch_statement.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/sem/value_expression.h"
|
||||||
#include "src/tint/type/void.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::BlockStatement* b) { return EmitBlock(b); },
|
||||||
[&](const ast::BreakStatement* b) { return EmitBreak(b); },
|
[&](const ast::BreakStatement* b) { return EmitBreak(b); },
|
||||||
[&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
|
[&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
|
||||||
// [&](const ast::CallStatement* c) {
|
[&](const ast::CallStatement* c) { return EmitCall(c); },
|
||||||
// TODO(dsinclair): Implement
|
|
||||||
// },
|
|
||||||
// [&](const ast::CompoundAssignmentStatement* c) {
|
// [&](const ast::CompoundAssignmentStatement* c) {
|
||||||
// TODO(dsinclair): Implement
|
// TODO(dsinclair): Implement
|
||||||
// },
|
// },
|
||||||
|
@ -593,9 +601,7 @@ utils::Result<Value*> BuilderImpl::EmitExpression(const ast::Expression* expr) {
|
||||||
// },
|
// },
|
||||||
[&](const ast::BinaryExpression* b) { return EmitBinary(b); },
|
[&](const ast::BinaryExpression* b) { return EmitBinary(b); },
|
||||||
[&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
|
[&](const ast::BitcastExpression* b) { return EmitBitcast(b); },
|
||||||
// [&](const ast::CallExpression* c) {
|
[&](const ast::CallExpression* c) { return EmitCall(c); },
|
||||||
// TODO(dsinclair): Implement
|
|
||||||
// },
|
|
||||||
// [&](const ast::IdentifierExpression* i) {
|
// [&](const ast::IdentifierExpression* i) {
|
||||||
// TODO(dsinclair): Implement
|
// TODO(dsinclair): Implement
|
||||||
// },
|
// },
|
||||||
|
@ -743,6 +749,63 @@ utils::Result<Value*> BuilderImpl::EmitBitcast(const ast::BitcastExpression* exp
|
||||||
return instr->Result();
|
return instr->Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallStatement* stmt) {
|
||||||
|
return EmitCall(stmt->expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
|
utils::Vector<Value*, 8> 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<sem::Call>(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<sem::Builtin>()) {
|
||||||
|
// TODO(dsinclair): .. something ...
|
||||||
|
diagnostics_.add_error(tint::diag::System::IR, "Missing builtin function support",
|
||||||
|
expr->source);
|
||||||
|
} else if (sem->Target()->As<sem::ValueConstructor>()) {
|
||||||
|
instr = builder.Construct(ty, std::move(args));
|
||||||
|
} else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
|
||||||
|
auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
|
||||||
|
instr = builder.Convert(ty, from, std::move(args));
|
||||||
|
} else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
|
||||||
|
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<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
|
utils::Result<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
|
||||||
auto* sem = program_->Sem().Get(lit);
|
auto* sem = program_->Sem().Get(lit);
|
||||||
if (!sem) {
|
if (!sem) {
|
||||||
|
|
|
@ -39,6 +39,8 @@ class BitcastExpression;
|
||||||
class BlockStatement;
|
class BlockStatement;
|
||||||
class BreakIfStatement;
|
class BreakIfStatement;
|
||||||
class BreakStatement;
|
class BreakStatement;
|
||||||
|
class CallExpression;
|
||||||
|
class CallStatement;
|
||||||
class ContinueStatement;
|
class ContinueStatement;
|
||||||
class Expression;
|
class Expression;
|
||||||
class ForLoopStatement;
|
class ForLoopStatement;
|
||||||
|
@ -61,6 +63,9 @@ class Loop;
|
||||||
class Switch;
|
class Switch;
|
||||||
class Terminator;
|
class Terminator;
|
||||||
} // namespace tint::ir
|
} // namespace tint::ir
|
||||||
|
namespace tint::sem {
|
||||||
|
class Builtin;
|
||||||
|
} // namespace tint::sem
|
||||||
|
|
||||||
namespace tint::ir {
|
namespace tint::ir {
|
||||||
|
|
||||||
|
@ -165,6 +170,16 @@ class BuilderImpl {
|
||||||
/// @returns the value storing the result if successful, utils::Failure otherwise
|
/// @returns the value storing the result if successful, utils::Failure otherwise
|
||||||
utils::Result<Value*> EmitBitcast(const ast::BitcastExpression* expr);
|
utils::Result<Value*> 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<Value*> 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<Value*> EmitCall(const ast::CallExpression* expr);
|
||||||
|
|
||||||
/// Emits a literal expression
|
/// Emits a literal expression
|
||||||
/// @param lit the literal to emit
|
/// @param lit the literal to emit
|
||||||
/// @returns true if successful, false otherwise
|
/// @returns true if successful, false otherwise
|
||||||
|
|
|
@ -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<ir::Block>());
|
||||||
|
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<ir::Block>());
|
||||||
|
EXPECT_EQ(d.AsString(), R"(%1 (vec3<f32>) = construct(vec3<f32>)
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
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<ir::Block>());
|
||||||
|
EXPECT_EQ(d.AsString(), R"(%2 (vec3<f32>) = construct(vec3<f32>, 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<ir::Block>());
|
||||||
|
EXPECT_EQ(d.AsString(), R"(%2 (f32) = convert(f32, i32, %1 (void))
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::ir
|
} // namespace tint::ir
|
||||||
|
|
|
@ -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<Value*> 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
|
|
@ -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<Call, Instruction> {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// @param result the result value
|
||||||
|
/// @param args the constructor arguments
|
||||||
|
Call(Value* result, utils::VectorRef<Value*> 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<Value*> 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<Value*, 1> args_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tint::ir
|
||||||
|
|
||||||
|
#endif // SRC_TINT_IR_CALL_H_
|
|
@ -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<Value*> 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
|
|
@ -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<Construct, Call> {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// @param result the result value
|
||||||
|
/// @param args the constructor arguments
|
||||||
|
Construct(Value* result, utils::VectorRef<Value*> 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_
|
|
@ -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<Value*> 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
|
|
@ -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<Convert, Call> {
|
||||||
|
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<Value*> 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_
|
|
@ -40,6 +40,8 @@ class TestHelperBase : public BASE, public ProgramBuilder {
|
||||||
/// return the same builder without rebuilding.
|
/// return the same builder without rebuilding.
|
||||||
/// @return the builder
|
/// @return the builder
|
||||||
BuilderImpl& CreateBuilder() {
|
BuilderImpl& CreateBuilder() {
|
||||||
|
SetResolveOnBuild(true);
|
||||||
|
|
||||||
if (gen_) {
|
if (gen_) {
|
||||||
return *gen_;
|
return *gen_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<Value*> 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
|
|
@ -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<UserCall, Call> {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// @param result the result value
|
||||||
|
/// @param name the function name
|
||||||
|
/// @param args the function arguments
|
||||||
|
UserCall(Value* result, Symbol name, utils::VectorRef<Value*> 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_
|
Loading…
Reference in New Issue