From 642a4f1d8c94e684c21a7fc47b75cfeee8ff656d Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Tue, 2 May 2023 08:27:28 +0000 Subject: [PATCH] [ir] Make dump output more consistent. This Cl updates the dump output for the IR to be a bit more consistent. Brackets are removed, named calls are used in place of symbols. Trailing commas cleaned up. Values have their type appended to make it clearer what they are when a literal is emitted. Bug: tint:1718 Change-Id: Ie202d4a4f8267d00b9af4864063b7133f4c7f324 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/130000 Kokoro: Kokoro Auto-Submit: Dan Sinclair Reviewed-by: Ben Clayton Reviewed-by: James Price Commit-Queue: Ben Clayton --- src/tint/ir/binary.cc | 39 +- src/tint/ir/binary_test.cc | 36 +- src/tint/ir/bitcast.cc | 3 +- src/tint/ir/bitcast_test.cc | 2 +- src/tint/ir/block.h | 2 +- src/tint/ir/builder_impl_test.cc | 836 ++++++++++++++++--------------- src/tint/ir/builtin.cc | 3 +- src/tint/ir/constant.cc | 22 +- src/tint/ir/constant_test.cc | 8 +- src/tint/ir/construct.cc | 8 +- src/tint/ir/convert.cc | 3 +- src/tint/ir/disassembler.cc | 96 +++- src/tint/ir/flow_node.h | 7 +- src/tint/ir/store.cc | 4 +- src/tint/ir/store_test.cc | 2 +- src/tint/ir/unary.cc | 11 +- src/tint/ir/unary_test.cc | 10 +- src/tint/ir/user_call.cc | 6 +- 18 files changed, 576 insertions(+), 522 deletions(-) diff --git a/src/tint/ir/binary.cc b/src/tint/ir/binary.cc index 9621b3ea8e..d3e3548564 100644 --- a/src/tint/ir/binary.cc +++ b/src/tint/ir/binary.cc @@ -31,67 +31,66 @@ Binary::~Binary() = default; utils::StringStream& Binary::ToInstruction(utils::StringStream& out) const { ToValue(out) << " = "; - lhs_->ToValue(out) << " "; switch (GetKind()) { case Binary::Kind::kAdd: - out << "+"; + out << "add"; break; case Binary::Kind::kSubtract: - out << "-"; + out << "sub"; break; case Binary::Kind::kMultiply: - out << "*"; + out << "mul"; break; case Binary::Kind::kDivide: - out << "/"; + out << "div"; break; case Binary::Kind::kModulo: - out << "%"; + out << "mod"; break; case Binary::Kind::kAnd: - out << "&"; + out << "bit_and"; break; case Binary::Kind::kOr: - out << "|"; + out << "bit_or"; break; case Binary::Kind::kXor: - out << "^"; + out << "bit_xor"; break; case Binary::Kind::kLogicalAnd: - out << "&&"; + out << "log_and"; break; case Binary::Kind::kLogicalOr: - out << "||"; + out << "log_or"; break; case Binary::Kind::kEqual: - out << "=="; + out << "eq"; break; case Binary::Kind::kNotEqual: - out << "!="; + out << "neq"; break; case Binary::Kind::kLessThan: - out << "<"; + out << "lt"; break; case Binary::Kind::kGreaterThan: - out << ">"; + out << "gt"; break; case Binary::Kind::kLessThanEqual: - out << "<="; + out << "lte"; break; case Binary::Kind::kGreaterThanEqual: - out << ">="; + out << "gte"; break; case Binary::Kind::kShiftLeft: - out << "<<"; + out << "shiftl"; break; case Binary::Kind::kShiftRight: - out << ">>"; + out << "shiftr"; break; } out << " "; + lhs_->ToValue(out) << ", "; rhs_->ToValue(out); - return out; } diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc index 5868c9524e..e03a61d1a4 100644 --- a/src/tint/ir/binary_test.cc +++ b/src/tint/ir/binary_test.cc @@ -45,7 +45,7 @@ TEST_F(IR_InstructionTest, CreateAnd) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 & 2"); + EXPECT_EQ(str.str(), "%1(i32) = bit_and 4i, 2i"); } TEST_F(IR_InstructionTest, CreateOr) { @@ -69,7 +69,7 @@ TEST_F(IR_InstructionTest, CreateOr) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 | 2"); + EXPECT_EQ(str.str(), "%1(i32) = bit_or 4i, 2i"); } TEST_F(IR_InstructionTest, CreateXor) { @@ -93,7 +93,7 @@ TEST_F(IR_InstructionTest, CreateXor) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 ^ 2"); + EXPECT_EQ(str.str(), "%1(i32) = bit_xor 4i, 2i"); } TEST_F(IR_InstructionTest, CreateLogicalAnd) { @@ -117,7 +117,7 @@ TEST_F(IR_InstructionTest, CreateLogicalAnd) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 && 2"); + EXPECT_EQ(str.str(), "%1(bool) = log_and 4i, 2i"); } TEST_F(IR_InstructionTest, CreateLogicalOr) { @@ -141,7 +141,7 @@ TEST_F(IR_InstructionTest, CreateLogicalOr) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 || 2"); + EXPECT_EQ(str.str(), "%1(bool) = log_or 4i, 2i"); } TEST_F(IR_InstructionTest, CreateEqual) { @@ -165,7 +165,7 @@ TEST_F(IR_InstructionTest, CreateEqual) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 == 2"); + EXPECT_EQ(str.str(), "%1(bool) = eq 4i, 2i"); } TEST_F(IR_InstructionTest, CreateNotEqual) { @@ -189,7 +189,7 @@ TEST_F(IR_InstructionTest, CreateNotEqual) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 != 2"); + EXPECT_EQ(str.str(), "%1(bool) = neq 4i, 2i"); } TEST_F(IR_InstructionTest, CreateLessThan) { @@ -213,7 +213,7 @@ TEST_F(IR_InstructionTest, CreateLessThan) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 < 2"); + EXPECT_EQ(str.str(), "%1(bool) = lt 4i, 2i"); } TEST_F(IR_InstructionTest, CreateGreaterThan) { @@ -237,7 +237,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThan) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 > 2"); + EXPECT_EQ(str.str(), "%1(bool) = gt 4i, 2i"); } TEST_F(IR_InstructionTest, CreateLessThanEqual) { @@ -261,7 +261,7 @@ TEST_F(IR_InstructionTest, CreateLessThanEqual) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 <= 2"); + EXPECT_EQ(str.str(), "%1(bool) = lte 4i, 2i"); } TEST_F(IR_InstructionTest, CreateGreaterThanEqual) { @@ -285,7 +285,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThanEqual) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = 4 >= 2"); + EXPECT_EQ(str.str(), "%1(bool) = gte 4i, 2i"); } TEST_F(IR_InstructionTest, CreateShiftLeft) { @@ -309,7 +309,7 @@ TEST_F(IR_InstructionTest, CreateShiftLeft) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 << 2"); + EXPECT_EQ(str.str(), "%1(i32) = shiftl 4i, 2i"); } TEST_F(IR_InstructionTest, CreateShiftRight) { @@ -333,7 +333,7 @@ TEST_F(IR_InstructionTest, CreateShiftRight) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 >> 2"); + EXPECT_EQ(str.str(), "%1(i32) = shiftr 4i, 2i"); } TEST_F(IR_InstructionTest, CreateAdd) { @@ -357,7 +357,7 @@ TEST_F(IR_InstructionTest, CreateAdd) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 + 2"); + EXPECT_EQ(str.str(), "%1(i32) = add 4i, 2i"); } TEST_F(IR_InstructionTest, CreateSubtract) { @@ -381,7 +381,7 @@ TEST_F(IR_InstructionTest, CreateSubtract) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 - 2"); + EXPECT_EQ(str.str(), "%1(i32) = sub 4i, 2i"); } TEST_F(IR_InstructionTest, CreateMultiply) { @@ -405,7 +405,7 @@ TEST_F(IR_InstructionTest, CreateMultiply) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 * 2"); + EXPECT_EQ(str.str(), "%1(i32) = mul 4i, 2i"); } TEST_F(IR_InstructionTest, CreateDivide) { @@ -429,7 +429,7 @@ TEST_F(IR_InstructionTest, CreateDivide) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 / 2"); + EXPECT_EQ(str.str(), "%1(i32) = div 4i, 2i"); } TEST_F(IR_InstructionTest, CreateModulo) { @@ -453,7 +453,7 @@ TEST_F(IR_InstructionTest, CreateModulo) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = 4 % 2"); + EXPECT_EQ(str.str(), "%1(i32) = mod 4i, 2i"); } TEST_F(IR_InstructionTest, Binary_Usage) { diff --git a/src/tint/ir/bitcast.cc b/src/tint/ir/bitcast.cc index dffbf21721..70f412ceed 100644 --- a/src/tint/ir/bitcast.cc +++ b/src/tint/ir/bitcast.cc @@ -25,9 +25,8 @@ Bitcast::Bitcast(uint32_t id, const type::Type* type, Value* val) Bitcast::~Bitcast() = default; utils::StringStream& Bitcast::ToInstruction(utils::StringStream& out) const { - ToValue(out) << " = bitcast("; + ToValue(out) << " = bitcast "; EmitArgs(out); - out << ")"; return out; } diff --git a/src/tint/ir/bitcast_test.cc b/src/tint/ir/bitcast_test.cc index f973b27e9a..a70fb9285f 100644 --- a/src/tint/ir/bitcast_test.cc +++ b/src/tint/ir/bitcast_test.cc @@ -39,7 +39,7 @@ TEST_F(IR_InstructionTest, Bitcast) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = bitcast(4)"); + EXPECT_EQ(str.str(), "%1(i32) = bitcast 4i"); } TEST_F(IR_InstructionTest, Bitcast_Usage) { diff --git a/src/tint/ir/block.h b/src/tint/ir/block.h index e83d43a698..39813552b4 100644 --- a/src/tint/ir/block.h +++ b/src/tint/ir/block.h @@ -33,7 +33,7 @@ class Block : public utils::Castable { /// @returns true if this is a dead block. This can happen in the case like a loop merge block /// which is never reached. - bool IsDead() const { return branch.target == nullptr; } + bool IsDead() const override { return branch.target == nullptr; } /// The node this block branches too. Branch branch = {}; diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 6efd69cfe4..3cd3c60731 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -42,10 +42,10 @@ TEST_F(IR_BuilderImplTest, Func) { EXPECT_EQ(1u, f->start_target->inbound_branches.Length()); EXPECT_EQ(1u, f->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function f - %bb1 = Block - Return () -FunctionEnd + EXPECT_EQ(Disassemble(m), R"(%fn0 = func f + %fn1 = block + ret +func_end )"); } @@ -88,23 +88,23 @@ TEST_F(IR_BuilderImplTest, IfStatement) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = if (true) + %fn2 = if true [t: %fn3, f: %fn4, m: %fn5] # true branch - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn5 # false branch - %bb5 = Block - BranchTo %bb4 () + %fn4 = block + branch %fn5 # if merge - %bb4 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -136,22 +136,22 @@ TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(2u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = if (true) + %fn2 = if true [t: %fn3, f: %fn4, m: %fn5] # true branch - %bb3 = Block - Return () + %fn3 = block + ret # false branch - %bb4 = Block - BranchTo %bb5 () + %fn4 = block + branch %fn5 # if merge - %bb5 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -183,22 +183,22 @@ TEST_F(IR_BuilderImplTest, IfStatement_FalseReturns) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(2u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = if (true) + %fn2 = if true [t: %fn3, f: %fn4, m: %fn5] # true branch - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn5 # false branch - %bb5 = Block - Return () + %fn4 = block + ret # if merge - %bb4 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -230,18 +230,18 @@ TEST_F(IR_BuilderImplTest, IfStatement_BothReturn) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(2u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = if (true) + %fn2 = if true [t: %fn3, f: %fn4] # true branch - %bb3 = Block - Return () + %fn3 = block + ret # false branch - %bb4 = Block - Return () -FunctionEnd + %fn4 = block + ret +func_end )"); } @@ -273,36 +273,32 @@ TEST_F(IR_BuilderImplTest, IfStatement_JumpChainToMerge) { ASSERT_NE(loop_flow->continuing.target, nullptr); ASSERT_NE(loop_flow->merge.target, nullptr); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = if (true) + %fn2 = if true [t: %fn3, f: %fn4, m: %fn5] # true branch - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn6 - %bb4 = loop + %fn6 = loop [s: %fn7, m: %fn8] # loop start - %bb5 = Block - BranchTo %bb6 () - - # loop continuing - %bb7 = Block - BranchTo %bb5 () + %fn7 = block + branch %fn8 # loop merge - %bb6 = Block - BranchTo %bb8 () + %fn8 = block + branch %fn5 # false branch - %bb9 = Block - BranchTo %bb8 () + %fn4 = block + branch %fn5 # if merge - %bb8 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -334,23 +330,19 @@ TEST_F(IR_BuilderImplTest, Loop_WithBreak) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, m: %fn4] # loop start - %bb3 = Block - BranchTo %bb4 () - - # loop continuing - %bb5 = Block - BranchTo %bb3 () + %fn3 = block + branch %fn4 # loop merge - %bb4 = Block - Return () -FunctionEnd + %fn4 = block + ret +func_end )"); } @@ -396,36 +388,36 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinue) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, c: %fn4, m: %fn5] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn6 - %bb4 = if (true) + %fn6 = if true [t: %fn7, f: %fn8, m: %fn9] # true branch - %bb5 = Block - BranchTo %bb6 () + %fn7 = block + branch %fn5 # false branch - %bb7 = Block - BranchTo %bb8 () + %fn8 = block + branch %fn9 # if merge - %bb8 = Block - BranchTo %bb9 () + %fn9 = block + branch %fn4 # loop continuing - %bb9 = Block - BranchTo %bb3 () + %fn4 = block + branch %fn3 # loop merge - %bb6 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -471,36 +463,36 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinuing_BreakIf) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, c: %fn4, m: %fn5] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn4 # loop continuing - %bb4 = Block - BranchTo %bb5 () + %fn4 = block + branch %fn6 - %bb5 = if (true) + %fn6 = if true [t: %fn7, f: %fn8, m: %fn9] # true branch - %bb6 = Block - BranchTo %bb7 () + %fn7 = block + branch %fn5 # false branch - %bb8 = Block - BranchTo %bb9 () + %fn8 = block + branch %fn9 # if merge - %bb9 = Block - BranchTo %bb3 () + %fn9 = block + branch %fn3 # loop merge - %bb7 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -546,34 +538,32 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, c: %fn4] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn5 - %bb4 = if (true) + %fn5 = if true [t: %fn6, f: %fn7, m: %fn8] # true branch - %bb5 = Block - Return () + %fn6 = block + ret # false branch - %bb6 = Block - BranchTo %bb7 () + %fn7 = block + branch %fn8 # if merge - %bb7 = Block - BranchTo %bb8 () + %fn8 = block + branch %fn4 # loop continuing - %bb8 = Block - BranchTo %bb3 () + %fn4 = block + branch %fn3 - # loop merge - # Dead -FunctionEnd +func_end )"); } @@ -605,21 +595,15 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3] # loop start - %bb3 = Block - Return () - # loop continuing - %bb4 = Block - BranchTo %bb3 () - - # loop merge - # Dead -FunctionEnd + %fn3 = block + ret +func_end )"); } @@ -629,6 +613,9 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn_ContinuingBreakIf) { // `ast_if` below), it doesn't get emitted as there is no way to reach the // loop merge due to the loop itself doing a `return`. This is why the // loop merge gets marked as Dead and the `ast_if` doesn't appear. + // + // Similar, the continuing block goes away as there is no way to get there, so it's treated + // as dead code and dropped. auto* ast_break_if = BreakIf(true); auto* ast_loop = Loop(Block(Return()), Block(ast_break_if)); auto* ast_if = If(true, Block(Return())); @@ -670,34 +657,15 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn_ContinuingBreakIf) { // This is 1 because only the loop branch happens. The subsequent if return is dead code. EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3] # loop start - %bb3 = Block - Return () - # loop continuing - %bb4 = Block - BranchTo %bb5 () - - %bb5 = if (true) - # true branch - %bb6 = Block - BranchTo %bb7 () - - # false branch - %bb8 = Block - BranchTo %bb9 () - - # if merge - %bb9 = Block - BranchTo %bb3 () - - # loop merge - # Dead -FunctionEnd + %fn3 = block + ret +func_end )"); } @@ -743,32 +711,28 @@ TEST_F(IR_BuilderImplTest, Loop_WithIf_BothBranchesBreak) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, m: %fn4] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn5 - %bb4 = if (true) + %fn5 = if true [t: %fn6, f: %fn7] # true branch - %bb5 = Block - BranchTo %bb6 () + %fn6 = block + branch %fn4 # false branch - %bb7 = Block - BranchTo %bb6 () - - # loop continuing - %bb8 = Block - BranchTo %bb3 () + %fn7 = block + branch %fn4 # loop merge - %bb6 = Block - Return () -FunctionEnd + %fn4 = block + ret +func_end )"); } @@ -893,114 +857,110 @@ TEST_F(IR_BuilderImplTest, Loop_Nested) { EXPECT_EQ(1u, func->start_target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, c: %fn4, m: %fn5] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn6 - %bb4 = loop + %fn6 = loop [s: %fn7, c: %fn8, m: %fn9] # loop start - %bb5 = Block - BranchTo %bb6 () + %fn7 = block + branch %fn10 - %bb6 = if (true) + %fn10 = if true [t: %fn11, f: %fn12, m: %fn13] # true branch - %bb7 = Block - BranchTo %bb8 () + %fn11 = block + branch %fn9 # false branch - %bb9 = Block - BranchTo %bb10 () + %fn12 = block + branch %fn13 # if merge - %bb10 = Block - BranchTo %bb11 () + %fn13 = block + branch %fn14 - %bb11 = if (true) + %fn14 = if true [t: %fn15, f: %fn16, m: %fn17] # true branch - %bb12 = Block - BranchTo %bb13 () + %fn15 = block + branch %fn8 # false branch - %bb14 = Block - BranchTo %bb15 () + %fn16 = block + branch %fn17 # if merge - %bb15 = Block - BranchTo %bb13 () + %fn17 = block + branch %fn8 # loop continuing - %bb13 = Block - BranchTo %bb16 () + %fn8 = block + branch %fn18 - %bb16 = loop + %fn18 = loop [s: %fn19, m: %fn20] # loop start - %bb17 = Block - BranchTo %bb18 () - - # loop continuing - %bb19 = Block - BranchTo %bb17 () + %fn19 = block + branch %fn20 # loop merge - %bb18 = Block - BranchTo %bb20 () + %fn20 = block + branch %fn21 - %bb20 = loop + %fn21 = loop [s: %fn22, c: %fn23, m: %fn24] # loop start - %bb21 = Block - BranchTo %bb22 () + %fn22 = block + branch %fn23 # loop continuing - %bb22 = Block - BranchTo %bb23 () + %fn23 = block + branch %fn25 - %bb23 = if (true) + %fn25 = if true [t: %fn26, f: %fn27, m: %fn28] # true branch - %bb24 = Block - BranchTo %bb25 () + %fn26 = block + branch %fn24 # false branch - %bb26 = Block - BranchTo %bb27 () + %fn27 = block + branch %fn28 # if merge - %bb27 = Block - BranchTo %bb21 () + %fn28 = block + branch %fn22 # loop merge - %bb25 = Block - BranchTo %bb5 () + %fn24 = block + branch %fn7 # loop merge - %bb8 = Block - BranchTo %bb28 () + %fn9 = block + branch %fn29 - %bb28 = if (true) + %fn29 = if true [t: %fn30, f: %fn31, m: %fn32] # true branch - %bb29 = Block - BranchTo %bb30 () + %fn30 = block + branch %fn5 # false branch - %bb31 = Block - BranchTo %bb32 () + %fn31 = block + branch %fn32 # if merge - %bb32 = Block - BranchTo %bb33 () + %fn32 = block + branch %fn4 # loop continuing - %bb33 = Block - BranchTo %bb3 () + %fn4 = block + branch %fn3 # loop merge - %bb30 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -1041,36 +1001,36 @@ TEST_F(IR_BuilderImplTest, While) { EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length()); EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, c: %fn4, m: %fn5] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn6 - %bb4 = if (false) + %fn6 = if false [t: %fn7, f: %fn8, m: %fn9] # true branch - %bb5 = Block - BranchTo %bb6 () + %fn7 = block + branch %fn9 # false branch - %bb7 = Block - BranchTo %bb8 () + %fn8 = block + branch %fn5 # if merge - %bb6 = Block - BranchTo %bb9 () + %fn9 = block + branch %fn4 # loop continuing - %bb9 = Block - BranchTo %bb3 () + %fn4 = block + branch %fn3 # loop merge - %bb8 = Block - Return () -FunctionEnd + %fn5 = block + ret +func_end )"); } @@ -1111,35 +1071,31 @@ TEST_F(IR_BuilderImplTest, While_Return) { EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length()); EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, m: %fn4] # loop start - %bb3 = Block - BranchTo %bb4 () + %fn3 = block + branch %fn5 - %bb4 = if (true) + %fn5 = if true [t: %fn6, f: %fn7, m: %fn8] # true branch - %bb5 = Block - BranchTo %bb6 () + %fn6 = block + branch %fn8 # false branch - %bb7 = Block - BranchTo %bb8 () + %fn7 = block + branch %fn4 # if merge - %bb6 = Block - Return () - # loop continuing - %bb9 = Block - BranchTo %bb3 () - + %fn8 = block + ret # loop merge - %bb8 = Block - Return () -FunctionEnd + %fn4 = block + ret +func_end )"); } @@ -1222,23 +1178,19 @@ TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) { EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = loop + %fn2 = loop [s: %fn3, m: %fn4] # loop start - %bb3 = Block - BranchTo %bb4 () - - # loop continuing - %bb5 = Block - BranchTo %bb3 () + %fn3 = block + branch %fn4 # loop merge - %bb4 = Block - Return () -FunctionEnd + %fn4 = block + ret +func_end )"); } @@ -1285,27 +1237,83 @@ TEST_F(IR_BuilderImplTest, Switch) { EXPECT_EQ(3u, flow->merge.target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = Switch (1) - # Case 0 - %bb3 = Block - BranchTo %bb4 () + %fn2 = switch 1i [c: (0i, %fn3), c: (1i, %fn4), c: (default, %fn5), m: %fn6] + # case 0i + %fn3 = block + branch %fn6 - # Case 1 - %bb5 = Block - BranchTo %bb4 () + # case 1i + %fn4 = block + branch %fn6 - # Case default - %bb6 = Block - BranchTo %bb4 () + # case default + %fn5 = block + branch %fn6 - # Switch Merge - %bb4 = Block - Return () -FunctionEnd + # switch merge + %fn6 = block + ret +func_end + +)"); +} + +TEST_F(IR_BuilderImplTest, Switch_MultiSelector) { + auto* ast_switch = Switch( + 1_i, + utils::Vector{Case( + utils::Vector{CaseSelector(0_i), CaseSelector(1_i), DefaultCaseSelector()}, Block())}); + + WrapInFunction(ast_switch); + + auto r = Build(); + ASSERT_TRUE(r) << Error(); + auto m = r.Move(); + + auto* ir_switch = FlowNodeForAstNode(ast_switch); + ASSERT_NE(ir_switch, nullptr); + ASSERT_TRUE(ir_switch->Is()); + + auto* flow = ir_switch->As(); + ASSERT_NE(flow->merge.target, nullptr); + ASSERT_EQ(1u, flow->cases.Length()); + + ASSERT_EQ(1u, m.functions.Length()); + auto* func = m.functions[0]; + + ASSERT_EQ(3u, flow->cases[0].selectors.Length()); + ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is>()); + EXPECT_EQ(0_i, + flow->cases[0].selectors[0].val->value->As>()->ValueOf()); + + ASSERT_TRUE(flow->cases[0].selectors[1].val->value->Is>()); + EXPECT_EQ(1_i, + flow->cases[0].selectors[1].val->value->As>()->ValueOf()); + + EXPECT_TRUE(flow->cases[0].selectors[2].IsDefault()); + + EXPECT_EQ(1u, flow->inbound_branches.Length()); + EXPECT_EQ(1u, flow->cases[0].start.target->inbound_branches.Length()); + EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length()); + EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); + + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 + + %fn2 = switch 1i [c: (0i 1i default, %fn3), m: %fn4] + # case 0i 1i default + %fn3 = block + branch %fn4 + + # switch merge + %fn4 = block + ret +func_end )"); } @@ -1337,19 +1345,19 @@ TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) { EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length()); EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = Switch (1) - # Case default - %bb3 = Block - BranchTo %bb4 () + %fn2 = switch 1i [c: (default, %fn3), m: %fn4] + # case default + %fn3 = block + branch %fn4 - # Switch Merge - %bb4 = Block - Return () -FunctionEnd + # switch merge + %fn4 = block + ret +func_end )"); } @@ -1390,23 +1398,23 @@ TEST_F(IR_BuilderImplTest, Switch_WithBreak) { // This is 1 because the if is dead-code eliminated and the return doesn't happen. EXPECT_EQ(1u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = Switch (1) - # Case 0 - %bb3 = Block - BranchTo %bb4 () + %fn2 = switch 1i [c: (0i, %fn3), c: (default, %fn4), m: %fn5] + # case 0i + %fn3 = block + branch %fn5 - # Case default - %bb5 = Block - BranchTo %bb4 () + # case default + %fn4 = block + branch %fn5 - # Switch Merge - %bb4 = Block - Return () -FunctionEnd + # switch merge + %fn5 = block + ret +func_end )"); } @@ -1449,20 +1457,18 @@ TEST_F(IR_BuilderImplTest, Switch_AllReturn) { EXPECT_EQ(0u, flow->merge.target->inbound_branches.Length()); EXPECT_EQ(2u, func->end_target->inbound_branches.Length()); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - BranchTo %bb2 () + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + branch %fn2 - %bb2 = Switch (1) - # Case 0 - %bb3 = Block - Return () - # Case default - %bb4 = Block - Return () - # Switch Merge - # Dead -FunctionEnd + %fn2 = switch 1i [c: (0i, %fn3), c: (default, %fn4)] + # case 0i + %fn3 = block + ret + # case default + %fn4 = block + ret +func_end )"); } @@ -1565,8 +1571,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) + 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = add %1(u32), 4u )"); } @@ -1583,8 +1589,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) - 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = sub %1(u32), 4u )"); } @@ -1601,8 +1607,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) * 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = mul %1(u32), 4u )"); } @@ -1619,8 +1625,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) / 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = div %1(u32), 4u )"); } @@ -1637,8 +1643,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) % 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = mod %1(u32), 4u )"); } @@ -1655,8 +1661,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) & 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = bit_and %1(u32), 4u )"); } @@ -1673,8 +1679,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) | 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = bit_or %1(u32), 4u )"); } @@ -1691,8 +1697,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) ^ 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = bit_xor %1(u32), 4u )"); } @@ -1709,8 +1715,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, ) -%2(bool) = %1(bool) && false + EXPECT_EQ(d.AsString(), R"(%1(bool) = call my_func +%2(bool) = log_and %1(bool), false )"); } @@ -1727,8 +1733,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, ) -%2(bool) = %1(bool) || true + EXPECT_EQ(d.AsString(), R"(%1(bool) = call my_func +%2(bool) = log_or %1(bool), true )"); } @@ -1745,8 +1751,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) == 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = eq %1(u32), 4u )"); } @@ -1763,8 +1769,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) != 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = neq %1(u32), 4u )"); } @@ -1781,8 +1787,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) < 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = lt %1(u32), 4u )"); } @@ -1799,8 +1805,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) > 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = gt %1(u32), 4u )"); } @@ -1817,8 +1823,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) <= 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = lte %1(u32), 4u )"); } @@ -1835,8 +1841,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(bool) = %1(u32) >= 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(bool) = gte %1(u32), 4u )"); } @@ -1853,8 +1859,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) << 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = shiftl %1(u32), 4u )"); } @@ -1871,8 +1877,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(u32) = call(my_func, ) -%2(u32) = %1(u32) >> 4 + EXPECT_EQ(d.AsString(), R"(%1(u32) = call my_func +%2(u32) = shiftr %1(u32), 4u )"); } @@ -1891,14 +1897,14 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(f32) = call(my_func, ) -%2(bool) = %1(f32) < 2.0 -%3(f32) = call(my_func, ) -%4(f32) = call(my_func, ) -%5(f32) = 2.29999995231628417969 * %4(f32) -%6(f32) = %3(f32) / %5(f32) -%7(bool) = 2.5 > %6(f32) -%8(bool) = %2(bool) && %7(bool) + EXPECT_EQ(d.AsString(), R"(%1(f32) = call my_func +%2(bool) = lt %1(f32), 2.0f +%3(f32) = call my_func +%4(f32) = call my_func +%5(f32) = mul 2.29999995231628417969f, %4(f32) +%6(f32) = div %3(f32), %5(f32) +%7(bool) = gt 2.5f, %6(f32) +%8(bool) = log_and %2(bool), %7(bool) )"); } @@ -1916,7 +1922,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound_WithConstEval) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(bool) = call(my_func, false) + EXPECT_EQ(d.AsString(), R"(%1(bool) = call my_func, false )"); } @@ -1934,8 +1940,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(f32) = call(my_func, ) -%2(f32) = bitcast(%1(f32)) + EXPECT_EQ(d.AsString(), R"(%1(f32) = call my_func +%2(f32) = bitcast %1(f32) )"); } @@ -1960,7 +1966,7 @@ TEST_F(IR_BuilderImplTest, EmitStatement_Discard) { 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))); + auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a))); WrapInFunction(stmt); auto& b = CreateBuilder(); @@ -1971,7 +1977,7 @@ TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(void) = call(my_func, 6.0) + EXPECT_EQ(d.AsString(), R"(%1(void) = call my_func, 6.0f )"); } @@ -1990,7 +1996,7 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%1(vec3) = construct() + EXPECT_EQ(d.AsString(), R"(%1(vec3) = construct )"); } @@ -2008,7 +2014,7 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Construct) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%2(vec3) = construct(2.0, 3.0, %1(void)) + EXPECT_EQ(d.AsString(), R"(%2(vec3) = construct 2.0f, 3.0f, %1(void) )"); } @@ -2026,7 +2032,7 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Convert) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%2(f32) = convert(i32, %1(void)) + EXPECT_EQ(d.AsString(), R"(%2(f32) = convert i32, %1(void) )"); } @@ -2039,10 +2045,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_MaterializedCall) { ASSERT_TRUE(r) << Error(); auto m = r.Move(); - EXPECT_EQ(Disassemble(m), R"(%bb0 = Function test_function - %bb1 = Block - Return (2.0) -FunctionEnd + EXPECT_EQ(Disassemble(m), R"(%fn0 = func test_function + %fn1 = block + ret 2.0f +func_end )"); } @@ -2061,7 +2067,7 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Builtin) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); - EXPECT_EQ(d.AsString(), R"(%2(f32) = asin(%1(void)) + EXPECT_EQ(d.AsString(), R"(%2(f32) = asin %1(void) )"); } diff --git a/src/tint/ir/builtin.cc b/src/tint/ir/builtin.cc index 54d2b98d58..54cf882bf3 100644 --- a/src/tint/ir/builtin.cc +++ b/src/tint/ir/builtin.cc @@ -29,9 +29,8 @@ Builtin::Builtin(uint32_t id, Builtin::~Builtin() = default; utils::StringStream& Builtin::ToInstruction(utils::StringStream& out) const { - ToValue(out) << " = " << builtin::str(func_) << "("; + ToValue(out) << " = " << builtin::str(func_) << " "; EmitArgs(out); - out << ")"; return out; } diff --git a/src/tint/ir/constant.cc b/src/tint/ir/constant.cc index e96415fa85..0666e918b2 100644 --- a/src/tint/ir/constant.cc +++ b/src/tint/ir/constant.cc @@ -35,27 +35,33 @@ utils::StringStream& Constant::ToValue(utils::StringStream& out) const { c, [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, - [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, - [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, - [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, - [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { + out << scalar->ValueAs().value << "i"; + }, + [&](const constant::Scalar* scalar) { + out << scalar->ValueAs().value << "u"; + }, + [&](const constant::Scalar* scalar) { + out << scalar->ValueAs().value << "f"; + }, + [&](const constant::Scalar* scalar) { + out << scalar->ValueAs().value << "h"; + }, [&](const constant::Scalar* scalar) { out << (scalar->ValueAs() ? "true" : "false"); }, [&](const constant::Splat* splat) { - out << splat->Type()->FriendlyName() << "("; + out << splat->Type()->FriendlyName() << " "; emit(splat->Index(0)); - out << ")"; }, [&](const constant::Composite* composite) { - out << composite->Type()->FriendlyName() << "("; + out << composite->Type()->FriendlyName() << " "; for (const auto* elem : composite->elements) { if (elem != composite->elements[0]) { out << ", "; } emit(elem); } - out << ")"; }); }; emit(value); diff --git a/src/tint/ir/constant_test.cc b/src/tint/ir/constant_test.cc index 1d05db7ee1..43d92b40db 100644 --- a/src/tint/ir/constant_test.cc +++ b/src/tint/ir/constant_test.cc @@ -32,7 +32,7 @@ TEST_F(IR_ConstantTest, f32) { EXPECT_EQ(1.2_f, c->value->As>()->ValueAs()); c->ToValue(str); - EXPECT_EQ("1.20000004768371582031", str.str()); + EXPECT_EQ("1.20000004768371582031f", str.str()); EXPECT_TRUE(c->value->Is>()); EXPECT_FALSE(c->value->Is>()); @@ -50,7 +50,7 @@ TEST_F(IR_ConstantTest, f16) { EXPECT_EQ(1.1_h, c->value->As>()->ValueAs()); c->ToValue(str); - EXPECT_EQ("1.099609375", str.str()); + EXPECT_EQ("1.099609375h", str.str()); EXPECT_FALSE(c->value->Is>()); EXPECT_TRUE(c->value->Is>()); @@ -68,7 +68,7 @@ TEST_F(IR_ConstantTest, i32) { EXPECT_EQ(1_i, c->value->As>()->ValueAs()); c->ToValue(str); - EXPECT_EQ("1", str.str()); + EXPECT_EQ("1i", str.str()); EXPECT_FALSE(c->value->Is>()); EXPECT_FALSE(c->value->Is>()); @@ -86,7 +86,7 @@ TEST_F(IR_ConstantTest, u32) { EXPECT_EQ(2_u, c->value->As>()->ValueAs()); c->ToValue(str); - EXPECT_EQ("2", str.str()); + EXPECT_EQ("2u", str.str()); EXPECT_FALSE(c->value->Is>()); EXPECT_FALSE(c->value->Is>()); diff --git a/src/tint/ir/construct.cc b/src/tint/ir/construct.cc index f71ba403a6..1507e8f86e 100644 --- a/src/tint/ir/construct.cc +++ b/src/tint/ir/construct.cc @@ -25,12 +25,8 @@ Construct::Construct(uint32_t id, const type::Type* type, utils::VectorRefFriendlyName() << ", "; + ToValue(out) << " = convert " << from_type_->FriendlyName() << ", "; EmitArgs(out); - out << ")"; return out; } diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc index 54c386ab08..53bf722918 100644 --- a/src/tint/ir/disassembler.cc +++ b/src/tint/ir/disassembler.cc @@ -89,7 +89,7 @@ void Disassembler::Walk(const FlowNode* node) { tint::Switch( node, [&](const ir::Function* f) { - Indent() << "%bb" << GetIdForNode(f) << " = Function " << f->name.Name() << std::endl; + Indent() << "%fn" << GetIdForNode(f) << " = func " << f->name.Name() << std::endl; { ScopedIndent func_indent(&indent_size_); @@ -101,27 +101,28 @@ void Disassembler::Walk(const FlowNode* node) { [&](const ir::Block* b) { // If this block is dead, nothing to do if (b->IsDead()) { - Indent() << "# Dead" << std::endl; return; } - Indent() << "%bb" << GetIdForNode(b) << " = Block" << std::endl; + Indent() << "%fn" << GetIdForNode(b) << " = block" << std::endl; EmitBlockInstructions(b); if (b->branch.target->Is()) { - Indent() << "Return"; + Indent() << "ret"; } else { - Indent() << "BranchTo " - << "%bb" << GetIdForNode(b->branch.target); + Indent() << "branch " + << "%fn" << GetIdForNode(b->branch.target); } - out_ << " ("; - for (const auto* v : b->branch.args) { - if (v != b->branch.args.Front()) { - out_ << ", "; + if (!b->branch.args.IsEmpty()) { + out_ << " "; + for (const auto* v : b->branch.args) { + if (v != b->branch.args.Front()) { + out_ << ", "; + } + v->ToValue(out_); } - v->ToValue(out_); } - out_ << ")" << std::endl; + out_ << std::endl; if (!b->branch.target->Is()) { out_ << std::endl; @@ -130,15 +131,37 @@ void Disassembler::Walk(const FlowNode* node) { Walk(b->branch.target); }, [&](const ir::Switch* s) { - Indent() << "%bb" << GetIdForNode(s) << " = Switch ("; + Indent() << "%fn" << GetIdForNode(s) << " = switch "; s->condition->ToValue(out_); - out_ << ")" << std::endl; + out_ << " ["; + for (const auto& c : s->cases) { + if (&c != &s->cases.Front()) { + out_ << ", "; + } + out_ << "c: ("; + for (const auto& selector : c.selectors) { + if (&selector != &c.selectors.Front()) { + out_ << " "; + } + + if (selector.IsDefault()) { + out_ << "default"; + } else { + selector.val->ToValue(out_); + } + } + out_ << ", %fn" << GetIdForNode(c.start.target) << ")"; + } + if (s->merge.target->IsConnected()) { + out_ << ", m: %fn" << GetIdForNode(s->merge.target); + } + out_ << "]" << std::endl; { ScopedIndent switch_indent(&indent_size_); ScopedStopNode scope(&stop_nodes_, s->merge.target); for (const auto& c : s->cases) { - Indent() << "# Case "; + Indent() << "# case "; for (const auto& selector : c.selectors) { if (&selector != &c.selectors.Front()) { out_ << " "; @@ -155,13 +178,20 @@ void Disassembler::Walk(const FlowNode* node) { } } - Indent() << "# Switch Merge" << std::endl; - Walk(s->merge.target); + if (s->merge.target->IsConnected()) { + Indent() << "# switch merge" << std::endl; + Walk(s->merge.target); + } }, [&](const ir::If* i) { - Indent() << "%bb" << GetIdForNode(i) << " = if ("; + Indent() << "%fn" << GetIdForNode(i) << " = if "; i->condition->ToValue(out_); - out_ << ")" << std::endl; + out_ << " [t: %fn" << GetIdForNode(i->true_.target) << ", f: %fn" + << GetIdForNode(i->false_.target); + if (i->merge.target->IsConnected()) { + out_ << ", m: %fn" << GetIdForNode(i->merge.target); + } + out_ << "]" << std::endl; { ScopedIndent if_indent(&indent_size_); @@ -174,13 +204,23 @@ void Disassembler::Walk(const FlowNode* node) { Walk(i->false_.target); } - if (!i->merge.target->IsDisconnected()) { + if (i->merge.target->IsConnected()) { Indent() << "# if merge" << std::endl; Walk(i->merge.target); } }, [&](const ir::Loop* l) { - Indent() << "%bb" << GetIdForNode(l) << " = loop" << std::endl; + Indent() << "%fn" << GetIdForNode(l) << " = loop [s: %fn" + << GetIdForNode(l->start.target); + + if (l->continuing.target->IsConnected()) { + out_ << ", c: %fn" << GetIdForNode(l->continuing.target); + } + if (l->merge.target->IsConnected()) { + out_ << ", m: %fn" << GetIdForNode(l->merge.target); + } + out_ << "]" << std::endl; + { ScopedStopNode loop_scope(&stop_nodes_, l->merge.target); ScopedIndent loop_indent(&indent_size_); @@ -190,14 +230,18 @@ void Disassembler::Walk(const FlowNode* node) { Walk(l->start.target); } - Indent() << "# loop continuing" << std::endl; - Walk(l->continuing.target); + if (l->continuing.target->IsConnected()) { + Indent() << "# loop continuing" << std::endl; + Walk(l->continuing.target); + } } - Indent() << "# loop merge" << std::endl; - Walk(l->merge.target); + if (l->merge.target->IsConnected()) { + Indent() << "# loop merge" << std::endl; + Walk(l->merge.target); + } }, - [&](const ir::Terminator*) { Indent() << "FunctionEnd" << std::endl + [&](const ir::Terminator*) { Indent() << "func_end" << std::endl << std::endl; }); } diff --git a/src/tint/ir/flow_node.h b/src/tint/ir/flow_node.h index 2a91674559..905f077605 100644 --- a/src/tint/ir/flow_node.h +++ b/src/tint/ir/flow_node.h @@ -32,8 +32,11 @@ class FlowNode : public utils::Castable { /// - Node is a continue target outside control flow (loop that returns) utils::Vector inbound_branches; - /// @returns true if this node has no inbound branches - bool IsDisconnected() const { return inbound_branches.IsEmpty(); } + /// @returns true if this node has inbound branches and branches out + bool IsConnected() const { return !IsDead() && !inbound_branches.IsEmpty(); } + + /// @returns true if the node does not branch out + virtual bool IsDead() const { return false; } protected: /// Constructor diff --git a/src/tint/ir/store.cc b/src/tint/ir/store.cc index 2680a2a3b5..8d3521498c 100644 --- a/src/tint/ir/store.cc +++ b/src/tint/ir/store.cc @@ -29,9 +29,9 @@ Store::Store(Value* to, Value* from) : Base(), to_(to), from_(from) { Store::~Store() = default; utils::StringStream& Store::ToInstruction(utils::StringStream& out) const { - out << "store("; + out << "store "; to_->ToValue(out) << ", "; - from_->ToValue(out) << ")"; + from_->ToValue(out); return out; } diff --git a/src/tint/ir/store_test.cc b/src/tint/ir/store_test.cc index d67e6d623a..82347dc73c 100644 --- a/src/tint/ir/store_test.cc +++ b/src/tint/ir/store_test.cc @@ -41,7 +41,7 @@ TEST_F(IR_InstructionTest, CreateStore) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "store(%0, 4)"); + EXPECT_EQ(str.str(), "store %0, 4i"); } TEST_F(IR_InstructionTest, Store_Usage) { diff --git a/src/tint/ir/unary.cc b/src/tint/ir/unary.cc index 9eb15093c7..f3c4f24752 100644 --- a/src/tint/ir/unary.cc +++ b/src/tint/ir/unary.cc @@ -31,21 +31,22 @@ utils::StringStream& Unary::ToInstruction(utils::StringStream& out) const { ToValue(out) << " = "; switch (GetKind()) { case Unary::Kind::kAddressOf: - out << "&"; + out << "addr_of"; break; case Unary::Kind::kComplement: - out << "~"; + out << "bit_complement"; break; case Unary::Kind::kIndirection: - out << "*"; + out << "indirection"; break; case Unary::Kind::kNegation: - out << "-"; + out << "negation"; break; case Unary::Kind::kNot: - out << "!"; + out << "log_not"; break; } + out << " "; val_->ToValue(out); return out; } diff --git a/src/tint/ir/unary_test.cc b/src/tint/ir/unary_test.cc index ada6103668..ff247a2fc4 100644 --- a/src/tint/ir/unary_test.cc +++ b/src/tint/ir/unary_test.cc @@ -45,7 +45,7 @@ TEST_F(IR_InstructionTest, CreateAddressOf) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(ptr) = &4"); + EXPECT_EQ(str.str(), "%1(ptr) = addr_of 4i"); } TEST_F(IR_InstructionTest, CreateComplement) { @@ -63,7 +63,7 @@ TEST_F(IR_InstructionTest, CreateComplement) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = ~4"); + EXPECT_EQ(str.str(), "%1(i32) = bit_complement 4i"); } TEST_F(IR_InstructionTest, CreateIndirection) { @@ -83,7 +83,7 @@ TEST_F(IR_InstructionTest, CreateIndirection) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = *4"); + EXPECT_EQ(str.str(), "%1(i32) = indirection 4i"); } TEST_F(IR_InstructionTest, CreateNegation) { @@ -101,7 +101,7 @@ TEST_F(IR_InstructionTest, CreateNegation) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(i32) = -4"); + EXPECT_EQ(str.str(), "%1(i32) = negation 4i"); } TEST_F(IR_InstructionTest, CreateNot) { @@ -119,7 +119,7 @@ TEST_F(IR_InstructionTest, CreateNot) { utils::StringStream str; inst->ToInstruction(str); - EXPECT_EQ(str.str(), "%1(bool) = !true"); + EXPECT_EQ(str.str(), "%1(bool) = log_not true"); } TEST_F(IR_InstructionTest, Unary_Usage) { diff --git a/src/tint/ir/user_call.cc b/src/tint/ir/user_call.cc index bd58d70d42..f23a2cab5c 100644 --- a/src/tint/ir/user_call.cc +++ b/src/tint/ir/user_call.cc @@ -25,9 +25,11 @@ UserCall::UserCall(uint32_t id, const type::Type* type, Symbol name, utils::Vect UserCall::~UserCall() = default; utils::StringStream& UserCall::ToInstruction(utils::StringStream& out) const { - ToValue(out) << " = call(" << name_.Name() << ", "; + ToValue(out) << " = call " << name_.Name(); + if (Args().Length() > 0) { + out << ", "; + } EmitArgs(out); - out << ")"; return out; }