mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-12 16:15:55 +00:00
[tint][ir][ToProgram] Begin flow node traversal
Traverse the block nodes, and if statements. Bug: tint:1902 Change-Id: Ie5533acdc65378bfea91b46a62090c4d3216b303 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/133100 Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
0b9cb101bf
commit
1ea1e1a375
@ -19,6 +19,7 @@
|
|||||||
#include "src/tint/ir/block.h"
|
#include "src/tint/ir/block.h"
|
||||||
#include "src/tint/ir/call.h"
|
#include "src/tint/ir/call.h"
|
||||||
#include "src/tint/ir/constant.h"
|
#include "src/tint/ir/constant.h"
|
||||||
|
#include "src/tint/ir/function_terminator.h"
|
||||||
#include "src/tint/ir/if.h"
|
#include "src/tint/ir/if.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/module.h"
|
#include "src/tint/ir/module.h"
|
||||||
@ -67,38 +68,40 @@ class State {
|
|||||||
// TODO(crbug.com/tint/1915): Properly implement this when we've fleshed out Function
|
// TODO(crbug.com/tint/1915): Properly implement this when we've fleshed out Function
|
||||||
utils::Vector<const ast::Parameter*, 1> params{};
|
utils::Vector<const ast::Parameter*, 1> params{};
|
||||||
ast::Type ret_ty;
|
ast::Type ret_ty;
|
||||||
auto* body = Block(fn->start_target);
|
auto* body = FlowNodeGraph(fn->start_target, fn->end_target);
|
||||||
utils::Vector<const ast::Attribute*, 1> attrs{};
|
utils::Vector<const ast::Attribute*, 1> attrs{};
|
||||||
utils::Vector<const ast::Attribute*, 1> ret_attrs{};
|
utils::Vector<const ast::Attribute*, 1> ret_attrs{};
|
||||||
b.Func(name, std::move(params), ret_ty, body, std::move(attrs), std::move(ret_attrs));
|
b.Func(name, std::move(params), ret_ty, body, std::move(attrs), std::move(ret_attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::BlockStatement* Block(const ir::Block* block) {
|
const ast::BlockStatement* FlowNodeGraph(const ir::FlowNode* node,
|
||||||
|
const ir::FlowNode* stop_at) {
|
||||||
// TODO(crbug.com/tint/1902): Check if the block is dead
|
// TODO(crbug.com/tint/1902): Check if the block is dead
|
||||||
utils::Vector<const ast::Statement*, decltype(ir::Block::instructions)::static_length>
|
utils::Vector<const ast::Statement*,
|
||||||
|
decltype(ast::BlockStatement::statements)::static_length>
|
||||||
stmts;
|
stmts;
|
||||||
for (auto* inst : block->instructions) {
|
while (node != stop_at) {
|
||||||
auto* stmt = Stmt(inst);
|
if (!node) {
|
||||||
if (!stmt) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
stmts.Push(stmt);
|
node = Switch(
|
||||||
}
|
|
||||||
return b.Block(std::move(stmts));
|
|
||||||
}
|
|
||||||
|
|
||||||
const ast::Statement* FlowNode(const ir::FlowNode* node) {
|
|
||||||
// TODO(crbug.com/tint/1902): Check the node is connected
|
|
||||||
return Switch(
|
|
||||||
node, //
|
node, //
|
||||||
[&](const ir::If* i) {
|
[&](const ir::Block* block) -> const ir::FlowNode* {
|
||||||
auto* cond = Expr(i->condition);
|
for (auto* inst : block->instructions) {
|
||||||
auto* t = Branch(i->true_);
|
if (auto* stmt = Stmt(inst); TINT_LIKELY(stmt)) {
|
||||||
if (auto* f = Branch(i->false_)) {
|
stmts.Push(stmt);
|
||||||
return b.If(cond, t, b.Else(f));
|
} else {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
// TODO(crbug.com/tint/1902): Emit merge block
|
}
|
||||||
return b.If(cond, t);
|
return block->branch.target;
|
||||||
|
},
|
||||||
|
[&](const ir::If* if_) -> const ir::FlowNode* {
|
||||||
|
if (auto* stmt = If(if_); TINT_LIKELY(stmt)) {
|
||||||
|
stmts.Push(stmt);
|
||||||
|
return if_->merge.target;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
},
|
},
|
||||||
[&](Default) {
|
[&](Default) {
|
||||||
TINT_UNIMPLEMENTED(IR, b.Diagnostics())
|
TINT_UNIMPLEMENTED(IR, b.Diagnostics())
|
||||||
@ -107,15 +110,33 @@ class State {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::BlockStatement* Branch(const ir::Branch& branch) {
|
return b.Block(std::move(stmts));
|
||||||
auto* stmt = FlowNode(branch.target);
|
|
||||||
if (!stmt) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
if (auto* block = stmt->As<ast::BlockStatement>()) {
|
|
||||||
return block;
|
const ast::IfStatement* If(const ir::If* i) {
|
||||||
|
auto* cond = Expr(i->condition);
|
||||||
|
auto* t = FlowNodeGraph(i->true_.target, i->merge.target);
|
||||||
|
if (!IsEmpty(i->false_.target, i->merge.target)) {
|
||||||
|
// TODO(crbug.com/tint/1902): Merge if else
|
||||||
|
auto* f = FlowNodeGraph(i->false_.target, i->merge.target);
|
||||||
|
return b.If(cond, t, b.Else(f));
|
||||||
}
|
}
|
||||||
return b.Block(stmt);
|
return b.If(cond, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return true if there are no instructions between @p node and and @p stop_at
|
||||||
|
bool IsEmpty(const ir::FlowNode* node, const ir::FlowNode* stop_at) {
|
||||||
|
while (node != stop_at) {
|
||||||
|
if (auto* block = node->As<ir::Block>()) {
|
||||||
|
if (block->instructions.Length() > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
node = block->branch.target;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ast::Statement* Stmt(const ir::Instruction* inst) {
|
const ast::Statement* Stmt(const ir::Instruction* inst) {
|
||||||
|
@ -67,6 +67,9 @@ fn f() {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Function-scope var
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
TEST_F(IRToProgramRoundtripTest, FunctionScopeVar_i32) {
|
TEST_F(IRToProgramRoundtripTest, FunctionScopeVar_i32) {
|
||||||
Test(R"(
|
Test(R"(
|
||||||
fn f() {
|
fn f() {
|
||||||
@ -93,5 +96,85 @@ fn f() {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// If
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
TEST_F(IRToProgramRoundtripTest, If_CallFn) {
|
||||||
|
Test(R"(
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
var cond : bool = true;
|
||||||
|
if (cond) {
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IRToProgramRoundtripTest, If_CallFn_Else_CallFn) {
|
||||||
|
Test(R"(
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
var cond : bool = true;
|
||||||
|
if (cond) {
|
||||||
|
a();
|
||||||
|
} else {
|
||||||
|
b();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IRToProgramRoundtripTest, If_CallFn_ElseIf_CallFn) {
|
||||||
|
Test(R"(
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
var cond_a : bool = true;
|
||||||
|
var cond_b : bool = true;
|
||||||
|
if (cond_a) {
|
||||||
|
a();
|
||||||
|
} else if (cond_b) {
|
||||||
|
b();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)",
|
||||||
|
R"(
|
||||||
|
fn a() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
var cond_a : bool = true;
|
||||||
|
var cond_b : bool = true;
|
||||||
|
if (cond_a) {
|
||||||
|
a();
|
||||||
|
} else {
|
||||||
|
if (cond_b) {
|
||||||
|
b();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::ir
|
} // namespace tint::ir
|
||||||
|
Loading…
x
Reference in New Issue
Block a user