diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-05 10:52:33 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-05 10:52:33 +0800 |
commit | 6072655369db89d8c8ec0f79ef03f04f695f7459 (patch) | |
tree | d69db4dcfba3cca0064d689645e1dad06fe65063 | |
parent | d45ed7dacfb36edc80127ff90b1bdc0ca2279a2a (diff) | |
download | mrust-6072655369db89d8c8ec0f79ef03f04f695f7459.tar.gz |
MIR Gen - Drop InnerMoved early for cleaner logic
-rw-r--r-- | src/mir/from_hir.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 12 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 4 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 33 |
4 files changed, 41 insertions, 10 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 9b9ddf5c..b8085cdb 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -523,8 +523,8 @@ namespace { this->visit_node_ptr(node.m_true); if( m_builder.block_active() || m_builder.has_result() ) { m_builder.push_stmt_assign( node.span(), result_val.clone(), m_builder.get_result(node.m_true->span()) ); - m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); m_builder.end_split_arm(node.span(), scope, true); + m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); } else { m_builder.end_split_arm(node.span(), scope, false); diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 66877913..e7492df6 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -38,14 +38,17 @@ public: ~ScopeHandle(); }; +// TODO: Replace the first three states with just one (and flags for init/moved) enum class VarState { Uninit, // No value assigned yet - Init, // Initialised and valid at this point - MaybeMoved, // Possibly has been moved - //MaybeMovedInner, // Inner possibly has been moved Moved, // Definitely moved - InnerMoved, // The inner has been moved, but the container needs to be dropped Dropped, // Dropped (out of scope) + + InnerMoved, // The inner has been moved, but the container needs to be dropped + //MaybeMovedInner, // Inner possibly has been moved + MaybeMoved, // Possibly has been moved + + Init, // Initialised and valid at this point }; extern ::std::ostream& operator<<(::std::ostream& os, VarState x); @@ -88,6 +91,7 @@ class MirBuilder ::MIR::RValue m_result; bool m_result_valid; + // TODO: Extra information. //::std::vector<VarState> m_arg_states; ::std::vector<VarState> m_variable_states; ::std::vector<VarState> m_temporary_states; diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp index 6ad2cd95..5cf5ff1e 100644 --- a/src/mir/from_hir_match.cpp +++ b/src/mir/from_hir_match.cpp @@ -178,10 +178,10 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod builder.push_stmt_assign( arm.m_code->span(), result_val.clone(), builder.get_result(arm.m_code->span()) ); // - Drop all non-moved values from this scope builder.terminate_scope( arm.m_code->span(), mv$(drop_scope) ); + // - Split end match scope + builder.end_split_arm( arm.m_code->span(), match_scope, true ); // - Go to the next block builder.end_block( ::MIR::Terminator::make_Goto(next_block) ); - - builder.end_split_arm( arm.m_code->span(), match_scope, true ); } arm_code.push_back( mv$(ac) ); diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index c2667025..24972b10 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -480,7 +480,21 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r sd_split.arms.back().always_early_terminated = /*sd_split.arms.back().has_early_terminated &&*/ !reachable; - // TODO: Undo moves from within the other scope + // HACK: If this arm's end is reachable, convert InnerMoved (shallow drop) variable states to Moved + // - I'm not 100% sure this is the correct place for calling drop. + if( reachable ) + { + for(unsigned int i = 0; i < sd_split.arms.back().var_states.size(); i ++ ) + { + auto& vs = sd_split.arms.back().var_states[i]; + if( vs == VarState::InnerMoved ) { + // Emit the shallow drop + push_stmt_drop_shallow( sp, ::MIR::LValue::make_Variable(i) ); + vs = VarState::Moved; + } + } + } + sd_split.arms.push_back( {} ); } void MirBuilder::end_split_arm_early(const Span& sp) @@ -500,6 +514,16 @@ void MirBuilder::end_split_arm_early(const Span& sp) auto& sd = m_scopes[ m_scope_stack.back() ]; auto& sd_split = sd.data.as_Split(); sd_split.arms.back().has_early_terminated = true; + + for(unsigned int i = 0; i < sd_split.arms.back().var_states.size(); i ++ ) + { + auto& vs = sd_split.arms.back().var_states[i]; + if( vs == VarState::InnerMoved ) { + // Emit the shallow drop + push_stmt_drop_shallow( sp, ::MIR::LValue::make_Variable(i) ); + //vs = VarState::Dropped; + } + } } } void MirBuilder::complete_scope(ScopeDef& sd) @@ -546,7 +570,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) assert(i < changed.size()); if( changed[i] ) { - DEBUG("("<<new_states[i]<<","<<arm.var_states[i]<<")"); + DEBUG(i << " ("<<new_states[i]<<","<<arm.var_states[i]<<")"); switch(new_states[i]) { case VarState::Uninit: @@ -581,7 +605,9 @@ void MirBuilder::complete_scope(ScopeDef& sd) } break; case VarState::InnerMoved: - TODO(sd.span, "Handle InnerMoved in Split scope (new_states)"); + // Need to tag for conditional shallow drop? Or just do that at the end of the split? + // - End of the split means that the only optional state is outer drop. + TODO(sd.span, "Handle InnerMoved in Split scope (new_states) - " << i << " " << m_output.named_variables[i]); break; case VarState::MaybeMoved: // Already optional, don't change @@ -623,6 +649,7 @@ void MirBuilder::complete_scope(ScopeDef& sd) } else if( arm.changed_var_states[i] ) { + DEBUG(i << " (_,"<<arm.var_states[i]<<")"); changed[i] = true; new_states[i] = arm.var_states[i]; } |