summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-05 10:52:33 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-05 10:52:33 +0800
commit6072655369db89d8c8ec0f79ef03f04f695f7459 (patch)
treed69db4dcfba3cca0064d689645e1dad06fe65063 /src
parentd45ed7dacfb36edc80127ff90b1bdc0ca2279a2a (diff)
downloadmrust-6072655369db89d8c8ec0f79ef03f04f695f7459.tar.gz
MIR Gen - Drop InnerMoved early for cleaner logic
Diffstat (limited to 'src')
-rw-r--r--src/mir/from_hir.cpp2
-rw-r--r--src/mir/from_hir.hpp12
-rw-r--r--src/mir/from_hir_match.cpp4
-rw-r--r--src/mir/mir_builder.cpp33
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];
}