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; }