summaryrefslogtreecommitdiff
path: root/src/trans/codegen_c_structured.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/trans/codegen_c_structured.cpp')
-rw-r--r--src/trans/codegen_c_structured.cpp54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/trans/codegen_c_structured.cpp b/src/trans/codegen_c_structured.cpp
index 888f9a26..f35de9f8 100644
--- a/src/trans/codegen_c_structured.cpp
+++ b/src/trans/codegen_c_structured.cpp
@@ -28,6 +28,9 @@ bool NodeRef::has_target() const
(Switch,
return e.next_bb != SIZE_MAX;
),
+ (SwitchValue,
+ return e.next_bb != SIZE_MAX;
+ ),
(Loop,
return e.next_bb != SIZE_MAX;
)
@@ -51,6 +54,9 @@ size_t NodeRef::target() const
(Switch,
return e.next_bb;
),
+ (SwitchValue,
+ return e.next_bb;
+ ),
(Loop,
return e.next_bb;
)
@@ -164,6 +170,7 @@ public:
next_blocks.push_back( arms.back().target() );
}
}
+ // TODO: Make the next block common
::std::sort(next_blocks.begin(), next_blocks.end());
size_t exit_bb = SIZE_MAX;
if(!next_blocks.empty())
@@ -189,10 +196,55 @@ public:
}
}
refs.push_back(Node::make_Switch({ exit_bb, &te.val, mv$(arms) }));
+ // TODO: Continue with the exit bb?
stop = true;
),
(SwitchValue,
- TODO(Span(), "SwitchValue");
+ ::std::vector<NodeRef> arms;
+ ::std::vector<size_t> next_blocks;
+ for(auto& tgt : te.targets)
+ {
+ arms.push_back( process_node_ref(tgt) );
+ if( arms.back().has_target() )
+ {
+ next_blocks.push_back( arms.back().target() );
+ }
+ }
+ auto def_arm = process_node_ref(te.def_target);
+ if(def_arm.has_target())
+ {
+ next_blocks.push_back(def_arm.target());
+ }
+
+ // TODO: Make the next block common
+ ::std::sort(next_blocks.begin(), next_blocks.end());
+ size_t exit_bb = SIZE_MAX;
+ if(!next_blocks.empty())
+ {
+ size_t cur = next_blocks[0];
+ size_t cur_count = 0;
+ size_t max_count = 0;
+ for(auto b : next_blocks)
+ {
+ if(cur == b) {
+ cur_count ++;
+ }
+ else {
+ if( cur_count > max_count ) {
+ exit_bb = cur;
+ }
+ cur = b;
+ cur_count = 1;
+ }
+ }
+ if( cur_count > max_count ) {
+ exit_bb = cur;
+ }
+ }
+
+ refs.push_back(Node::make_SwitchValue({ exit_bb, &te.val, mv$(def_arm), mv$(arms), &te.values }));
+ stop = true;
+
),
(Call,
// NOTE: Let the panic arm just be a goto