[tint][ir][ToProgram] Emit returns without values

Returns with values requires fleshing out of functions, which comes next

Bug: tint:1902
Change-Id: I5f956805441b99038f2d48758d1bd767ea4e1a1d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133141
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2023-05-17 10:45:26 +00:00 committed by Dawn LUCI CQ
parent 6ab77f16f0
commit a6e7cfc1d0
2 changed files with 78 additions and 23 deletions

View File

@ -41,6 +41,10 @@
#include "src/tint/utils/transform.h" #include "src/tint/utils/transform.h"
#include "src/tint/utils/vector.h" #include "src/tint/utils/vector.h"
#define UNHANDLED_CASE(object_ptr) \
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) \
<< "unhandled case in Switch(): " << (object_ptr ? object_ptr->TypeInfo().name : "<null>")
namespace tint::ir { namespace tint::ir {
namespace { namespace {
@ -81,33 +85,43 @@ class State {
decltype(ast::BlockStatement::statements)::static_length> decltype(ast::BlockStatement::statements)::static_length>
stmts; stmts;
while (node != stop_at) { while (node != stop_at) {
if (!node) { enum Status { kContinue, kStop, kError };
return nullptr; Status status = Switch(
}
node = Switch(
node, // node, //
[&](const ir::Block* block) -> const ir::FlowNode* { [&](const ir::Block* block) {
for (auto* inst : block->instructions) { for (auto* inst : block->instructions) {
if (auto* stmt = Stmt(inst); TINT_LIKELY(stmt)) { if (auto* stmt = Stmt(inst); TINT_LIKELY(stmt)) {
stmts.Push(stmt); stmts.Push(stmt);
} else { } else {
return nullptr; return kError;
} }
} }
return block->branch.target; node = block->branch.target;
return kContinue;
}, },
[&](const ir::If* if_) -> const ir::FlowNode* { [&](const ir::If* if_) {
if (auto* stmt = If(if_); TINT_LIKELY(stmt)) { if (auto* stmt = If(if_); TINT_LIKELY(stmt)) {
stmts.Push(stmt); stmts.Push(stmt);
return if_->merge.target; node = if_->merge.target;
return node->inbound_branches.IsEmpty() ? kStop : kContinue;
} }
return nullptr; return kError;
},
[&](const ir::FunctionTerminator*) {
stmts.Push(b.Return());
return kStop;
}, },
[&](Default) { [&](Default) {
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) UNHANDLED_CASE(node);
<< "unhandled case in Switch(): " << node->TypeInfo().name; return kError;
return nullptr;
}); });
if (TINT_UNLIKELY(status == kError)) {
return nullptr;
}
if (status == kStop) {
break;
}
} }
return b.Block(std::move(stmts)); return b.Block(std::move(stmts));
@ -178,8 +192,7 @@ class State {
[&](const ir::Var* i) { return Var(i); }, // [&](const ir::Var* i) { return Var(i); }, //
[&](const ir::Store* i) { return Store(i); }, [&](const ir::Store* i) { return Store(i); },
[&](Default) { [&](Default) {
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) UNHANDLED_CASE(inst);
<< "unhandled case in Switch(): " << inst->TypeInfo().name;
return nullptr; return nullptr;
}); });
} }
@ -226,8 +239,7 @@ class State {
call, // call, //
[&](const ir::UserCall* c) { return b.Call(Sym(c->name), std::move(args)); }, [&](const ir::UserCall* c) { return b.Call(Sym(c->name), std::move(args)); },
[&](Default) { [&](Default) {
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) UNHANDLED_CASE(call);
<< "unhandled case in Switch(): " << call->TypeInfo().name;
return nullptr; return nullptr;
}); });
} }
@ -238,8 +250,7 @@ class State {
[&](const ir::Constant* c) { return ConstExpr(c); }, [&](const ir::Constant* c) { return ConstExpr(c); },
[&](const ir::Var* v) { return VarExpr(v); }, [&](const ir::Var* v) { return VarExpr(v); },
[&](Default) { [&](Default) {
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) UNHANDLED_CASE(val);
<< "unhandled case in Switch(): " << val->TypeInfo().name;
return nullptr; return nullptr;
}); });
} }
@ -253,8 +264,7 @@ class State {
[&](const type::F16*) { return b.Expr(c->value->ValueAs<f16>()); }, [&](const type::F16*) { return b.Expr(c->value->ValueAs<f16>()); },
[&](const type::Bool*) { return b.Expr(c->value->ValueAs<bool>()); }, [&](const type::Bool*) { return b.Expr(c->value->ValueAs<bool>()); },
[&](Default) { [&](Default) {
TINT_UNIMPLEMENTED(IR, b.Diagnostics()) UNHANDLED_CASE(c);
<< "unhandled case in Switch(): " << c->TypeInfo().name;
return nullptr; return nullptr;
}); });
} }
@ -327,7 +337,7 @@ class State {
}, },
[&](const type::Reference* r) { return Type(r->StoreType()); }, [&](const type::Reference* r) { return Type(r->StoreType()); },
[&](Default) { [&](Default) {
TINT_UNREACHABLE(IR, b.Diagnostics()) << "unhandled type: " << ty->TypeInfo().name; UNHANDLED_CASE(ty);
return ast::Type{}; return ast::Type{};
}); });
} }

View File

@ -60,13 +60,25 @@ TEST_F(IRToProgramRoundtripTest, EmptyModule) {
Test(""); Test("");
} }
TEST_F(IRToProgramRoundtripTest, EmptySingleFunction) { TEST_F(IRToProgramRoundtripTest, SingleFunction_Empty) {
Test(R"( Test(R"(
fn f() { fn f() {
} }
)"); )");
} }
TEST_F(IRToProgramRoundtripTest, SingleFunction_Return) {
Test(R"(
fn f() {
return;
}
)",
R"(
fn f() {
}
)");
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Function-scope var // Function-scope var
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -113,6 +125,20 @@ fn f() {
)"); )");
} }
TEST_F(IRToProgramRoundtripTest, If_Return) {
Test(R"(
fn a() {
}
fn f() {
var cond : bool = true;
if (cond) {
return;
}
}
)");
}
TEST_F(IRToProgramRoundtripTest, If_CallFn_Else_CallFn) { TEST_F(IRToProgramRoundtripTest, If_CallFn_Else_CallFn) {
Test(R"( Test(R"(
fn a() { fn a() {
@ -132,6 +158,25 @@ fn f() {
)"); )");
} }
TEST_F(IRToProgramRoundtripTest, If_Return_Else_Return) {
Test(R"(
fn a() {
}
fn b() {
}
fn f() {
var cond : bool = true;
if (cond) {
return;
} else {
return;
}
}
)");
}
TEST_F(IRToProgramRoundtripTest, If_CallFn_ElseIf_CallFn) { TEST_F(IRToProgramRoundtripTest, If_CallFn_ElseIf_CallFn) {
Test(R"( Test(R"(
fn a() { fn a() {