summaryrefslogtreecommitdiff
path: root/src/trans/codegen_c.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans/codegen_c.cpp')
-rw-r--r--src/trans/codegen_c.cpp162
1 files changed, 134 insertions, 28 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 04e37e35..3eff24a0 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -2030,14 +2030,110 @@ namespace {
}
const bool EMIT_STRUCTURED = false; // Saves time.
- const bool USE_STRUCTURED = false; // Still not correct.
+ const bool USE_STRUCTURED = true; // Still not correct.
if( EMIT_STRUCTURED )
{
m_of << "#if " << USE_STRUCTURED << "\n";
auto nodes = MIR_To_Structured(*code);
+
+ ::std::set<unsigned> goto_targets;
+ struct H {
+ static void find_goto_targets(const Node& n, ::std::set<unsigned>& goto_targets) {
+ switch(n.tag())
+ {
+ case Node::TAGDEAD: throw "";
+ TU_ARM(n, Block, ne) {
+ for(const auto& sn : ne.nodes)
+ {
+ if(sn.node)
+ find_goto_targets(*sn.node, goto_targets);
+ }
+ if(ne.next_bb != SIZE_MAX)
+ goto_targets.insert(ne.next_bb);
+ } break;
+ TU_ARM(n, If, ne) {
+ find_goto_targets_ref(ne.arm_true, goto_targets);
+ find_goto_targets_ref(ne.arm_false, goto_targets);
+ if(ne.next_bb != SIZE_MAX)
+ goto_targets.insert(ne.next_bb);
+ } break;
+ TU_ARM(n, Switch, ne) {
+ for(const auto& sn : ne.arms) {
+ find_goto_targets_ref(sn, goto_targets);
+ if( sn.has_target() && sn.target() != ne.next_bb )
+ {
+ goto_targets.insert(sn.target());
+ }
+ }
+ if(ne.next_bb != SIZE_MAX)
+ goto_targets.insert(ne.next_bb);
+ } break;
+ TU_ARM(n, SwitchValue, ne) {
+ for(const auto& sn : ne.arms)
+ {
+ find_goto_targets_ref(sn, goto_targets);
+ if( sn.has_target() && sn.target() != ne.next_bb )
+ {
+ goto_targets.insert(sn.target());
+ }
+ }
+ find_goto_targets_ref(ne.def_arm, goto_targets);
+ if( ne.def_arm.has_target() && ne.def_arm.target() != ne.next_bb )
+ {
+ goto_targets.insert(ne.def_arm.target());
+ }
+ if(ne.next_bb != SIZE_MAX)
+ goto_targets.insert(ne.next_bb);
+ } break;
+ TU_ARM(n, Loop, ne) {
+ assert(ne.code.node);
+ find_goto_targets(*ne.code.node, goto_targets);
+ if(ne.next_bb != SIZE_MAX)
+ goto_targets.insert(ne.next_bb);
+ } break;
+ }
+ }
+ static void find_goto_targets_ref(const NodeRef& r, ::std::set<unsigned>& goto_targets) {
+ if(r.node)
+ find_goto_targets(*r.node, goto_targets);
+ else
+ goto_targets.insert(r.bb_idx);
+ }
+ };
for(const auto& node : nodes)
{
- emit_fcn_node(mir_res, node, 1);
+ H::find_goto_targets(node, goto_targets);
+ }
+
+ for(const auto& node : nodes)
+ {
+ m_of << "\t" << "// Node\n";
+ emit_fcn_node(mir_res, node, 1, goto_targets);
+
+ switch(node.tag())
+ {
+ case Node::TAGDEAD: throw "";
+ TU_ARM(node, Block, e)
+ if( e.next_bb != SIZE_MAX )
+ m_of << "\t""goto bb" << e.next_bb << ";\n";
+ break;
+ TU_ARM(node, If, e)
+ if( e.next_bb != SIZE_MAX )
+ m_of << "\t""goto bb" << e.next_bb << ";\n";
+ break;
+ TU_ARM(node, Switch, e)
+ if( e.next_bb != SIZE_MAX )
+ m_of << "\t""goto bb" << e.next_bb << ";\n";
+ break;
+ TU_ARM(node, SwitchValue, e)
+ if( e.next_bb != SIZE_MAX )
+ m_of << "\t""goto bb" << e.next_bb << ";\n";
+ break;
+ TU_ARM(node, Loop, e)
+ if( e.next_bb != SIZE_MAX )
+ m_of << "\t""goto bb" << e.next_bb << ";\n";
+ break;
+ }
}
m_of << "#else\n";
@@ -2153,20 +2249,25 @@ namespace {
m_mir_res = nullptr;
}
- void emit_fcn_node(::MIR::TypeResolve& mir_res, const Node& node, unsigned indent_level)
+ void emit_fcn_node(::MIR::TypeResolve& mir_res, const Node& node, unsigned indent_level, const ::std::set<unsigned>& goto_targets)
{
+ TRACE_FUNCTION_F(node.tag_str());
auto indent = RepeatLitStr { "\t", static_cast<int>(indent_level) };
- TU_MATCHA( (node), (e),
- (Block,
+ switch(node.tag())
+ {
+ case Node::TAGDEAD: throw "";
+ TU_ARM(node, Block, e) {
for(size_t i = 0; i < e.nodes.size(); i ++)
{
const auto& snr = e.nodes[i];
if( snr.node ) {
- emit_fcn_node(mir_res, *snr.node, indent_level);
+ emit_fcn_node(mir_res, *snr.node, indent_level, goto_targets);
}
else {
- DEBUG(mir_res << "BB" << snr.bb_idx);
- m_of << indent << "bb" << snr.bb_idx << ":\n";
+ DEBUG(mir_res << "Block BB" << snr.bb_idx);
+ // TODO: Only emit the label if it's ever used as a goto target
+ if( goto_targets.count(snr.bb_idx) )
+ m_of << indent << "bb" << snr.bb_idx << ": (void)0;\n";
const auto& bb = mir_res.m_fcn.blocks.at(snr.bb_idx);
for(const auto& stmt : bb.statements)
{
@@ -2190,6 +2291,7 @@ namespace {
),
(If,
//assert(i == e.nodes.size()-1 && "If");
+ // - This is valid, the next node should be a If (but could be a loop)
),
(Call,
emit_term_call(mir_res, te, indent_level);
@@ -2203,11 +2305,13 @@ namespace {
)
}
}
- ),
- (If,
+ } break;
+ TU_ARM(node, If, e) {
m_of << indent << "if("; emit_lvalue(*e.val); m_of << ") {\n";
if( e.arm_true.node ) {
- emit_fcn_node(mir_res, *e.arm_true.node, indent_level+1);
+ emit_fcn_node(mir_res, *e.arm_true.node, indent_level+1, goto_targets);
+ if( e.arm_true.has_target() && e.arm_true.target() != e.next_bb )
+ m_of << indent << "\tgoto bb" << e.arm_true.target() << ";\n";
}
else {
m_of << indent << "\tgoto bb" << e.arm_true.bb_idx << ";\n";
@@ -2215,38 +2319,40 @@ namespace {
m_of << indent << "}\n";
m_of << indent << "else {\n";
if( e.arm_false.node ) {
- emit_fcn_node(mir_res, *e.arm_false.node, indent_level+1);
+ emit_fcn_node(mir_res, *e.arm_false.node, indent_level+1, goto_targets);
+ if( e.arm_false.has_target() && e.arm_false.target() != e.next_bb )
+ m_of << indent << "\tgoto bb" << e.arm_false.target() << ";\n";
}
else {
m_of << indent << "\tgoto bb" << e.arm_false.bb_idx << ";\n";
}
m_of << indent << "}\n";
- ),
- (Switch,
+ } break;
+ TU_ARM(node, Switch, e) {
this->emit_term_switch(mir_res, *e.val, e.arms.size(), indent_level, [&](auto idx) {
const auto& arm = e.arms.at(idx);
if( arm.node ) {
m_of << "{\n";
- this->emit_fcn_node(mir_res, *arm.node, indent_level+1);
- m_of << indent << "\t} ";
+ this->emit_fcn_node(mir_res, *arm.node, indent_level+1, goto_targets);
if( arm.has_target() && arm.target() != e.next_bb ) {
- m_of << "goto bb" << arm.target() << ";";
+ m_of << indent << "\t" << "goto bb" << arm.target() << ";\n";
}
else {
- m_of << "break;";
+ //m_of << "break;";
}
+ m_of << indent << "\t}";
}
else {
m_of << "goto bb" << arm.bb_idx << ";";
}
});
- ),
- (SwitchValue,
+ } break;
+ TU_ARM(node, SwitchValue, e) {
this->emit_term_switchvalue(mir_res, *e.val, *e.vals, indent_level, [&](auto idx) {
const auto& arm = (idx == SIZE_MAX ? e.def_arm : e.arms.at(idx));
if( arm.node ) {
m_of << "{\n";
- this->emit_fcn_node(mir_res, *arm.node, indent_level+1);
+ this->emit_fcn_node(mir_res, *arm.node, indent_level+1, goto_targets);
m_of << indent << "\t} ";
if( arm.has_target() && arm.target() != e.next_bb ) {
m_of << "goto bb" << arm.target() << ";";
@@ -2256,15 +2362,15 @@ namespace {
m_of << "goto bb" << arm.bb_idx << ";";
}
});
- ),
- (Loop,
+ } break;
+ TU_ARM(node, Loop, e) {
m_of << indent << "for(;;) {\n";
assert(e.code.node);
assert(e.code.node->is_Block());
- this->emit_fcn_node(mir_res, *e.code.node, indent_level+1);
+ this->emit_fcn_node(mir_res, *e.code.node, indent_level+1, goto_targets);
m_of << indent << "}\n";
- )
- )
+ } break;
+ }
}
bool type_is_emulated_i128(const ::HIR::TypeRef& ty) const
@@ -2768,7 +2874,7 @@ namespace {
}
else
{
- emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index); m_of << ";\n\t";
+ emit_lvalue(e.dst); m_of << ".TAG = "; emit_enum_variant_val(repr, ve.index); m_of << ";\n" << indent;
emit_lvalue(e.dst); m_of << ".DATA";
m_of << ".var_" << ve.index << " = "; emit_param(ve.val);
}
@@ -3047,7 +3153,7 @@ namespace {
m_of << indent << "case " << e->values[j] << ": ";
}
cb(j);
- m_of << "\n";
+ m_of << "break;\n";
}
m_of << indent << "default: abort();\n";
m_of << indent << "}\n";