[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 <noreply+kokoro@google.com> Auto-Submit: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com> Reviewed-by: James Price <jrprice@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
255a116ea1
commit
642a4f1d8c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -33,7 +33,7 @@ class Block : public utils::Castable<Block, FlowNode> {
|
|||
|
||||
/// @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 = {};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,27 +35,33 @@ utils::StringStream& Constant::ToValue(utils::StringStream& out) const {
|
|||
c,
|
||||
[&](const constant::Scalar<AFloat>* scalar) { out << scalar->ValueAs<AFloat>().value; },
|
||||
[&](const constant::Scalar<AInt>* scalar) { out << scalar->ValueAs<AInt>().value; },
|
||||
[&](const constant::Scalar<i32>* scalar) { out << scalar->ValueAs<i32>().value; },
|
||||
[&](const constant::Scalar<u32>* scalar) { out << scalar->ValueAs<u32>().value; },
|
||||
[&](const constant::Scalar<f32>* scalar) { out << scalar->ValueAs<f32>().value; },
|
||||
[&](const constant::Scalar<f16>* scalar) { out << scalar->ValueAs<f16>().value; },
|
||||
[&](const constant::Scalar<i32>* scalar) {
|
||||
out << scalar->ValueAs<i32>().value << "i";
|
||||
},
|
||||
[&](const constant::Scalar<u32>* scalar) {
|
||||
out << scalar->ValueAs<u32>().value << "u";
|
||||
},
|
||||
[&](const constant::Scalar<f32>* scalar) {
|
||||
out << scalar->ValueAs<f32>().value << "f";
|
||||
},
|
||||
[&](const constant::Scalar<f16>* scalar) {
|
||||
out << scalar->ValueAs<f16>().value << "h";
|
||||
},
|
||||
[&](const constant::Scalar<bool>* scalar) {
|
||||
out << (scalar->ValueAs<bool>() ? "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);
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST_F(IR_ConstantTest, f32) {
|
|||
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
|
||||
|
||||
c->ToValue(str);
|
||||
EXPECT_EQ("1.20000004768371582031", str.str());
|
||||
EXPECT_EQ("1.20000004768371582031f", str.str());
|
||||
|
||||
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
|
||||
|
@ -50,7 +50,7 @@ TEST_F(IR_ConstantTest, f16) {
|
|||
EXPECT_EQ(1.1_h, c->value->As<constant::Scalar<f16>>()->ValueAs<f16>());
|
||||
|
||||
c->ToValue(str);
|
||||
EXPECT_EQ("1.099609375", str.str());
|
||||
EXPECT_EQ("1.099609375h", str.str());
|
||||
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||
EXPECT_TRUE(c->value->Is<constant::Scalar<f16>>());
|
||||
|
@ -68,7 +68,7 @@ TEST_F(IR_ConstantTest, i32) {
|
|||
EXPECT_EQ(1_i, c->value->As<constant::Scalar<i32>>()->ValueAs<i32>());
|
||||
|
||||
c->ToValue(str);
|
||||
EXPECT_EQ("1", str.str());
|
||||
EXPECT_EQ("1i", str.str());
|
||||
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
|
||||
|
@ -86,7 +86,7 @@ TEST_F(IR_ConstantTest, u32) {
|
|||
EXPECT_EQ(2_u, c->value->As<constant::Scalar<u32>>()->ValueAs<u32>());
|
||||
|
||||
c->ToValue(str);
|
||||
EXPECT_EQ("2", str.str());
|
||||
EXPECT_EQ("2u", str.str());
|
||||
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
|
||||
|
|
|
@ -25,12 +25,8 @@ Construct::Construct(uint32_t id, const type::Type* type, utils::VectorRef<Value
|
|||
Construct::~Construct() = default;
|
||||
|
||||
utils::StringStream& Construct::ToInstruction(utils::StringStream& out) const {
|
||||
ToValue(out) << " = construct(";
|
||||
if (!Args().IsEmpty()) {
|
||||
out << ", ";
|
||||
EmitArgs(out);
|
||||
}
|
||||
out << ")";
|
||||
ToValue(out) << " = construct ";
|
||||
EmitArgs(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,8 @@ Convert::Convert(uint32_t id,
|
|||
Convert::~Convert() = default;
|
||||
|
||||
utils::StringStream& Convert::ToInstruction(utils::StringStream& out) const {
|
||||
ToValue(out) << " = convert(" << from_type_->FriendlyName() << ", ";
|
||||
ToValue(out) << " = convert " << from_type_->FriendlyName() << ", ";
|
||||
EmitArgs(out);
|
||||
out << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Terminator>()) {
|
||||
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<Terminator>()) {
|
||||
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; });
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,11 @@ class FlowNode : public utils::Castable<FlowNode> {
|
|||
/// - Node is a continue target outside control flow (loop that returns)
|
||||
utils::Vector<FlowNode*, 2> 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ TEST_F(IR_InstructionTest, CreateAddressOf) {
|
|||
|
||||
utils::StringStream str;
|
||||
inst->ToInstruction(str);
|
||||
EXPECT_EQ(str.str(), "%1(ptr<private, i32, read_write>) = &4");
|
||||
EXPECT_EQ(str.str(), "%1(ptr<private, i32, read_write>) = 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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue