[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:
parent
6ab77f16f0
commit
a6e7cfc1d0
|
@ -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{};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue