summaryrefslogtreecommitdiff
path: root/src/mir/from_hir_match.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir/from_hir_match.cpp')
-rw-r--r--src/mir/from_hir_match.cpp18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index d3c5a5eb..183d6418 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -120,8 +120,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
auto next_block = builder.new_bb_unlinked();
// 1. Stop the current block so we can generate code
- auto first_cmp_block = builder.new_bb_unlinked();
- builder.end_block( ::MIR::Terminator::make_Goto(first_cmp_block) );
+ auto first_cmp_block = builder.pause_cur_block();
struct H {
@@ -242,7 +241,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
t_arm_rules arm_rules;
for(unsigned int arm_idx = 0; arm_idx < node.m_arms.size(); arm_idx ++)
{
- DEBUG("ARM " << arm_idx);
+ TRACE_FUNCTION_FR("ARM " << arm_idx, "ARM" << arm_idx);
/*const*/ auto& arm = node.m_arms[arm_idx];
ArmCode ac;
@@ -251,6 +250,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
// - Define variables from the first pattern
conv.define_vars_from(node.span(), arm.m_patterns.front());
+ auto pat_scope = builder.new_scope_split(node.span());
for( unsigned int pat_idx = 0; pat_idx < arm.m_patterns.size(); pat_idx ++ )
{
const auto& pat = arm.m_patterns[pat_idx];
@@ -271,9 +271,11 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
ac.destructures.push_back( builder.new_bb_unlinked() );
builder.set_cur_block( ac.destructures.back() );
conv.destructure_from( arm.m_code->span(), pat, match_val.clone(), true );
+ builder.end_split_arm( arm.m_code->span(), pat_scope, /*reachable=*/false ); // HACK: Mark as not reachable, this scope isn't for codegen.
builder.pause_cur_block();
// NOTE: Paused block resumed upon successful match
}
+ builder.terminate_scope( arm.m_code->span(), mv$(pat_scope) );
// TODO: If this pattern ignores fields with Drop impls, this will lead to leaks.
// - Ideally, this would trigger a drop of whatever wasn't already taken by the pattern.
@@ -292,10 +294,13 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
ac.cond_start = builder.new_bb_unlinked();
builder.set_cur_block( ac.cond_start );
- // TODO: Temp scope.
+ auto tmp_scope = builder.new_scope_temp(arm.m_cond->span());
conv.visit_node_ptr( arm.m_cond );
ac.cond_lval = builder.get_result_in_lvalue(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool));
+ // NOTE: Terminating the scope slightly early is safe, because the resulting boolean temp isn't invalidated.
+ builder.terminate_scope( arm.m_code->span(), mv$(tmp_scope) );
ac.cond_end = builder.pause_cur_block();
+
// NOTE: Paused so that later code (which knows what the false branch will be) can end it correctly
// TODO: What to do with contidionals in the fast model?
@@ -309,10 +314,12 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
// Code
DEBUG("-- Body Code");
+
ac.code = builder.new_bb_unlinked();
auto tmp_scope = builder.new_scope_temp(arm.m_code->span());
builder.set_cur_block( ac.code );
conv.visit_node_ptr( arm.m_code );
+
if( !builder.block_active() && !builder.has_result() ) {
DEBUG("Arm diverged");
// Nothing need be done, as the block diverged.
@@ -325,7 +332,6 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
DEBUG("Arm result");
// - Set result
auto res = builder.get_result(arm.m_code->span());
- //builder.raise_variables( arm.m_code->span(), res );
builder.push_stmt_assign( arm.m_code->span(), result_val.clone(), mv$(res) );
// - Drop all non-moved values from this scope
builder.terminate_scope( arm.m_code->span(), mv$(tmp_scope) );
@@ -377,6 +383,8 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
DEBUG("> (" << arm_rule.arm_idx << ", " << arm_rule.pat_idx << ") - " << arm_rule.m_rules);
}
+ // TODO: Don't generate inner code until decisions are generated (keeps MIR flow nice)
+
// TODO: Detect if a rule is ordering-dependent. In this case we currently have to fall back on the simple match code
// - A way would be to search for `_` rules with non _ rules following. Would false-positive in some cases, but shouldn't false negative
// TODO: Merge equal rulesets if there's one with no condition.