[ir] Convert materialized nodes to constants
This CL updates the IR builder to convert materialized call expressions directly into the resulting constant values. Bug: tint:1718 Change-Id: I184478996afdd11b00ca946775eab6801b777f3c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122605 Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
af4ca3891f
commit
03ee23ea9e
|
@ -56,6 +56,7 @@
|
||||||
#include "src/tint/program.h"
|
#include "src/tint/program.h"
|
||||||
#include "src/tint/sem/builtin.h"
|
#include "src/tint/sem/builtin.h"
|
||||||
#include "src/tint/sem/call.h"
|
#include "src/tint/sem/call.h"
|
||||||
|
#include "src/tint/sem/materialize.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_constructor.h"
|
||||||
|
@ -751,6 +752,19 @@ utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallStatement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
|
// If this is a materialized semantic node, just use the constant value.
|
||||||
|
if (auto* mat = program_->Sem().Get(expr)) {
|
||||||
|
if (mat->ConstantValue()) {
|
||||||
|
auto* cv = mat->ConstantValue()->Clone(clone_ctx_);
|
||||||
|
if (!cv) {
|
||||||
|
add_error(expr->source, "failed to get constant value for call " +
|
||||||
|
std::string(expr->TypeInfo().name));
|
||||||
|
return utils::Failure;
|
||||||
|
}
|
||||||
|
return builder.Constant(cv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
utils::Vector<Value*, 8> args;
|
utils::Vector<Value*, 8> args;
|
||||||
args.Reserve(expr->args.Length());
|
args.Reserve(expr->args.Length());
|
||||||
|
|
||||||
|
@ -758,7 +772,7 @@ utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
for (const auto* arg : expr->args) {
|
for (const auto* arg : expr->args) {
|
||||||
auto value = EmitExpression(arg);
|
auto value = EmitExpression(arg);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
add_error(arg->source, "Failed to convert arguments");
|
add_error(arg->source, "failed to convert arguments");
|
||||||
return utils::Failure;
|
return utils::Failure;
|
||||||
}
|
}
|
||||||
args.Push(value.Get());
|
args.Push(value.Get());
|
||||||
|
@ -766,7 +780,7 @@ utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
|
|
||||||
auto* sem = program_->Sem().Get<sem::Call>(expr);
|
auto* sem = program_->Sem().Get<sem::Call>(expr);
|
||||||
if (!sem) {
|
if (!sem) {
|
||||||
add_error(expr->source, "Failed to get semantic information for call " +
|
add_error(expr->source, "failed to get semantic information for call " +
|
||||||
std::string(expr->TypeInfo().name));
|
std::string(expr->TypeInfo().name));
|
||||||
return utils::Failure;
|
return utils::Failure;
|
||||||
}
|
}
|
||||||
|
@ -778,14 +792,14 @@ utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
// If this is a builtin function, emit the specific builtin value
|
// If this is a builtin function, emit the specific builtin value
|
||||||
if (sem->Target()->As<sem::Builtin>()) {
|
if (sem->Target()->As<sem::Builtin>()) {
|
||||||
// TODO(dsinclair): .. something ...
|
// TODO(dsinclair): .. something ...
|
||||||
add_error(expr->source, "Missing builtin function support");
|
add_error(expr->source, "missing builtin function support");
|
||||||
} else if (sem->Target()->As<sem::ValueConstructor>()) {
|
} else if (sem->Target()->As<sem::ValueConstructor>()) {
|
||||||
instr = builder.Construct(ty, std::move(args));
|
instr = builder.Construct(ty, std::move(args));
|
||||||
} else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
|
} else if (auto* conv = sem->Target()->As<sem::ValueConversion>()) {
|
||||||
auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
|
auto* from = conv->Source()->Clone(clone_ctx_.type_ctx);
|
||||||
instr = builder.Convert(ty, from, std::move(args));
|
instr = builder.Convert(ty, from, std::move(args));
|
||||||
} else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
|
} else if (expr->target->identifier->Is<ast::TemplatedIdentifier>()) {
|
||||||
TINT_UNIMPLEMENTED(IR, diagnostics_) << "Missing templated ident support";
|
TINT_UNIMPLEMENTED(IR, diagnostics_) << "missing templated ident support";
|
||||||
return utils::Failure;
|
return utils::Failure;
|
||||||
} else {
|
} else {
|
||||||
// Not a builtin and not a templated call, so this is a user function.
|
// Not a builtin and not a templated call, so this is a user function.
|
||||||
|
@ -802,7 +816,7 @@ utils::Result<Value*> BuilderImpl::EmitCall(const ast::CallExpression* expr) {
|
||||||
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) {
|
||||||
add_error(lit->source, "Failed to get semantic information for node " +
|
add_error(lit->source, "failed to get semantic information for node " +
|
||||||
std::string(lit->TypeInfo().name));
|
std::string(lit->TypeInfo().name));
|
||||||
return utils::Failure;
|
return utils::Failure;
|
||||||
}
|
}
|
||||||
|
@ -810,7 +824,7 @@ utils::Result<Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit
|
||||||
auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
|
auto* cv = sem->ConstantValue()->Clone(clone_ctx_);
|
||||||
if (!cv) {
|
if (!cv) {
|
||||||
add_error(lit->source,
|
add_error(lit->source,
|
||||||
"Failed to get constant value for node " + std::string(lit->TypeInfo().name));
|
"failed to get constant value for node " + std::string(lit->TypeInfo().name));
|
||||||
return utils::Failure;
|
return utils::Failure;
|
||||||
}
|
}
|
||||||
return builder.Constant(cv);
|
return builder.Constant(cv);
|
||||||
|
|
|
@ -1876,9 +1876,12 @@ TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) {
|
// TODO(dsinclair): This needs assignment in order to output correctly. The empty constructor ends
|
||||||
|
// up materializing, so there is no expression to emit until there is a usage. When assigment is
|
||||||
|
// implemented this can be enabled (and the output updated).
|
||||||
|
TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) {
|
||||||
auto* expr = vec3(ty.f32());
|
auto* expr = vec3(ty.f32());
|
||||||
WrapInFunction(expr);
|
GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto& b = CreateBuilder();
|
||||||
InjectFlowBlock();
|
InjectFlowBlock();
|
||||||
|
@ -1923,5 +1926,22 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Convert) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IR_BuilderImplTest, EmitExpression_MaterializedCall) {
|
||||||
|
auto* expr = Return(Call("trunc", 2.5_f));
|
||||||
|
|
||||||
|
Func("test_function", {}, ty.f32(), expr, utils::Empty);
|
||||||
|
|
||||||
|
auto r = Build();
|
||||||
|
ASSERT_TRUE(r) << Error();
|
||||||
|
auto m = r.Move();
|
||||||
|
|
||||||
|
EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function
|
||||||
|
%bb1 = Block
|
||||||
|
Return (2.0)
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::ir
|
} // namespace tint::ir
|
||||||
|
|
Loading…
Reference in New Issue