diff options
Diffstat (limited to 'src/mir/from_hir_match.cpp')
-rw-r--r-- | src/mir/from_hir_match.cpp | 18 |
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. |