summaryrefslogtreecommitdiff
path: root/src/trans
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-11-05 10:30:45 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-11-05 10:30:45 +0800
commit840c541cd1a000bb29f68ea3c059863ea7260281 (patch)
tree72a197b570fe26a9fbb63c1230b14ab92e362586 /src/trans
parent715ab49457f5d797fae8b155f51142674fe0075c (diff)
downloadmrust-840c541cd1a000bb29f68ea3c059863ea7260281.tar.gz
MIR - Use SwitchValue terminator
Diffstat (limited to 'src/trans')
-rw-r--r--src/trans/codegen_c.cpp51
1 files changed, 49 insertions, 2 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 43a0c103..082d461d 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -1871,7 +1871,9 @@ namespace {
bb_use_counts[t] ++;
),
(SwitchValue,
- MIR_TODO(mir_res, "SwitchValue in C codegen");
+ for(const auto& t : te.targets)
+ bb_use_counts[t] ++;
+ bb_use_counts[te.def_target] ++;
),
(Call,
bb_use_counts[te.ret_block] ++;
@@ -2005,7 +2007,52 @@ namespace {
}
),
(SwitchValue,
- MIR_TODO(mir_res, "SwitchValue in C codegen");
+ if( const auto* ve = e.values.opt_String() ) {
+ assert(ve->size() == e.targets.size());
+ m_of << "\t{\n";
+ m_of << "\t\tint cmp;\n";
+ m_of << "\t\t";
+ for(size_t i = 0; i < e.targets.size(); i++)
+ {
+ const auto& v = (*ve)[i];
+ m_of << "if( (cmp = slice_cmp("; emit_lvalue(e.val); m_of << ", make_sliceptr("; this->print_escaped_string(v); m_of << "," << v.size() << "))) < 0)\n";
+ m_of << "\t\t\tgoto bb" << e.def_target << ";\n";
+ m_of << "\t\telse if( cmp == 0 )\n";
+ m_of << "\t\t\tgoto bb" << e.targets[i] << ";\n";
+ m_of << "\t\telse ";
+ }
+ m_of << "\n\t\t\tgoto bb" << e.def_target << ";\n";
+
+ m_of << "\t}\n";
+ }
+ else if( const auto* ve = e.values.opt_Unsigned() ) {
+ assert(ve->size() == e.targets.size());
+ m_of << "\tswitch("; emit_lvalue(e.val); m_of << ") {\n";
+ for(size_t i = 0; i < e.targets.size(); i++)
+ {
+ m_of << "\t\tcase " << (*ve)[i] << "ull: goto bb" << e.targets[i] << ";\n";
+ }
+ m_of << "\t\tdefault: goto bb" << e.def_target << ";\n";
+ m_of << "\t}\n";
+ }
+ else if( const auto* ve = e.values.opt_Signed() ) {
+ assert(ve->size() == e.targets.size());
+ m_of << "\tswitch("; emit_lvalue(e.val); m_of << ") {\n";
+ for(size_t i = 0; i < e.targets.size(); i++)
+ {
+ m_of << "\t\tcase ";
+ if( (*ve)[i] == INT64_MIN )
+ m_of << "INT64_MIN";
+ else
+ m_of << (*ve)[i] << "ull";
+ m_of << ": goto bb" << e.targets[i] << ";\n";
+ }
+ m_of << "\t\tdefault: goto bb" << e.def_target << ";\n";
+ m_of << "\t}\n";
+ }
+ else {
+ MIR_BUG(mir_res, "SwitchValue with unknown value type - " << e.values.tag_str());
+ }
),
(Call,
emit_term_call(mir_res, e, 1);