summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mir/from_hir.hpp5
-rw-r--r--src/mir/mir_builder.cpp59
2 files changed, 58 insertions, 6 deletions
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index 475087c7..c5d770af 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -42,7 +42,9 @@ 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)
};
extern ::std::ostream& operator<<(::std::ostream& os, VarState x);
@@ -86,6 +88,7 @@ class MirBuilder
::MIR::RValue m_result;
bool m_result_valid;
+ //::std::vector<VarState> m_arg_states;
::std::vector<VarState> m_variable_states;
::std::vector<VarState> m_temporary_states;
@@ -140,6 +143,8 @@ public:
void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val);
// Push a drop (likely only used by scope cleanup)
void push_stmt_drop(const Span& sp, ::MIR::LValue val);
+ // Push a shallow drop (for Box)
+ void push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val);
// - Block management
bool block_active() const {
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index b53a9356..f4f9db7e 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -259,6 +259,9 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
case VarState::MaybeMoved:
// ERROR? Temporaries shouldn't be resassigned after becoming valid
break;
+ case VarState::InnerMoved:
+ BUG(sp, "Reassigning inner-moved temporary - " << dst);
+ break;
case VarState::Init:
// ERROR. Temporaries are single-assignment
break;
@@ -270,6 +273,7 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
//m_return_valid = true;
),
(Variable,
+ // TODO: Ensure that slot is mutable (information is lost, assume true)
switch( get_variable_state(sp, e) )
{
case VarState::Uninit:
@@ -279,10 +283,12 @@ void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RVal
// TODO: Is this an error? The variable has descoped.
break;
case VarState::Init:
- // 1. Must be mut
- // 2. Drop (if not Copy)
+ // Drop (if not Copy) - Copy check is done within push_stmt_drop
push_stmt_drop( sp, dst.clone() );
break;
+ case VarState::InnerMoved:
+ push_stmt_drop_shallow( sp, dst.clone() );
+ break;
case VarState::MaybeMoved:
// TODO: Conditional drop
break;
@@ -304,6 +310,19 @@ void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val)
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::DEEP, mv$(val) }) );
}
+void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val)
+{
+ ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
+ ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, "");
+
+ // TODO: Ensure that the type is a Box
+ //if( lvalue_is_copy(sp, val) ) {
+ // // Don't emit a drop for Copy values
+ // return ;
+ //}
+
+ m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::SHALLOW, mv$(val) }) );
+}
void MirBuilder::set_cur_block(unsigned int new_block)
{
@@ -518,6 +537,9 @@ void MirBuilder::complete_scope(ScopeDef& sd)
case VarState::Moved:
new_states[i] = VarState::MaybeMoved;
break;
+ case VarState::InnerMoved:
+ TODO(sd.span, "Handle InnerMoved in Split scope (Init:arm.var_states)");
+ break;
case VarState::Dropped:
BUG(sd.span, "Dropped value in arm");
break;
@@ -527,6 +549,9 @@ void MirBuilder::complete_scope(ScopeDef& sd)
new_states[i] = VarState::MaybeMoved; // MaybeInit?
}
break;
+ case VarState::InnerMoved:
+ TODO(sd.span, "Handle InnerMoved in Split scope (new_states)");
+ break;
case VarState::MaybeMoved:
// Already optional, don't change
break;
@@ -547,6 +572,9 @@ void MirBuilder::complete_scope(ScopeDef& sd)
case VarState::Moved:
// No change
break;
+ case VarState::InnerMoved:
+ TODO(sd.span, "Handle InnerMoved in Split scope (Moved:arm.var_states)");
+ break;
case VarState::Dropped:
BUG(sd.span, "Dropped value in arm");
break;
@@ -881,9 +909,22 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd)
(Temporaries,
for(auto tmp_idx : ::reverse(e.temporaries))
{
- if( get_temp_state(sd.span, tmp_idx) == VarState::Init ) {
+ switch( get_temp_state(sd.span, tmp_idx) )
+ {
+ case VarState::Uninit:
+ case VarState::Dropped:
+ case VarState::Moved:
+ break;
+ case VarState::Init:
push_stmt_drop( sd.span, ::MIR::LValue::make_Temporary({ tmp_idx }) );
set_temp_state(sd.span, tmp_idx, VarState::Dropped);
+ break;
+ case VarState::InnerMoved:
+ push_stmt_drop_shallow( sd.span, ::MIR::LValue::make_Temporary({ tmp_idx }) );
+ set_temp_state(sd.span, tmp_idx, VarState::Dropped);
+ break;
+ case VarState::MaybeMoved:
+ BUG(sd.span, "Optionally moved temporary? - " << tmp_idx);
}
}
),
@@ -899,8 +940,11 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd)
case VarState::Init:
push_stmt_drop( sd.span, ::MIR::LValue::make_Variable(var_idx) );
break;
+ case VarState::InnerMoved:
+ push_stmt_drop_shallow( sd.span, ::MIR::LValue::make_Variable(var_idx) );
+ break;
case VarState::MaybeMoved:
- //TODO(Span(), "MaybeMoved");
+ //TODO(sd.span, "Include drop flags");
// TODO: Drop flags
break;
}
@@ -981,15 +1025,17 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv)
BUG(sp, "Box move out of invalid LValue " << inner_lv << " - should have been moved");
),
(Variable,
- TODO(sp, "Mark var " << ei << " for shallow drop");
+ set_variable_state(sp, ei, VarState::InnerMoved);
),
(Temporary,
- TODO(sp, "Mark temp " << ei.idx << " for shallow drop");
+ set_temp_state(sp, ei.idx, VarState::InnerMoved);
),
(Argument,
TODO(sp, "Mark arg " << ei.idx << " for shallow drop");
)
)
+ // Early return!
+ return ;
}
}
BUG(sp, "Move out of deref with non-Copy values - &move? - " << lv);
@@ -1032,6 +1078,7 @@ ScopeHandle::~ScopeHandle()
_(Init)
_(MaybeMoved)
_(Moved)
+ _(InnerMoved)
_(Dropped)
#undef _
}