diff options
-rw-r--r-- | src/mir/from_hir.cpp | 20 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 6 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 82 |
3 files changed, 77 insertions, 31 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index fe876686..a15ea8ef 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -530,16 +530,6 @@ namespace { } auto res = m_builder.get_result(node.span()); - // NOTE: `let foo = &bar();` is valid! - // - So is `let (ref foo, _) = (bar(), 1);` - // - Raising the variables if there's a borrow works for most - // cases, but not cases where the let causes an unsizing. - if( res.is_Borrow() ) - { - assert(m_block_tmp_scope); - m_builder.raise_variables(node.span(), res, *m_block_tmp_scope); - } - if( node.m_pattern.m_binding.is_valid() && node.m_pattern.m_data.is_Any() && node.m_pattern.m_binding.m_type == ::HIR::PatternBinding::Type::Move ) { m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Variable(node.m_pattern.m_binding.m_slot), mv$(res) ); @@ -663,7 +653,7 @@ namespace { if( m_builder.block_active() ) { auto res = m_builder.get_result(arm.m_code->span()); - m_builder.raise_variables( arm.m_code->span(), res, scope ); + m_builder.raise_variables( arm.m_code->span(), res, scope, /*to_above=*/true); m_builder.set_result(arm.m_code->span(), mv$(res)); m_builder.terminate_scope( node.span(), mv$(tmp_scope) ); @@ -682,7 +672,7 @@ namespace { const auto& sp = node.span(); auto res = m_builder.get_result(sp); - m_builder.raise_variables(sp, res, stmt_scope); + m_builder.raise_variables(sp, res, stmt_scope, /*to_above=*/true); m_builder.set_result(sp, mv$(res)); m_builder.terminate_scope( node.span(), mv$(stmt_scope) ); @@ -1499,6 +1489,7 @@ namespace { // TODO: Proper panic handling, including scope destruction m_builder.set_cur_block(place__panic); + //m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() ); // TODO: Drop `place` m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); m_builder.set_cur_block(place__ok); @@ -1523,6 +1514,7 @@ namespace { // TODO: Proper panic handling, including scope destruction m_builder.set_cur_block(place_raw__panic); + //m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() ); // TODO: Drop `place` m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); m_builder.set_cur_block(place_raw__ok); @@ -1559,11 +1551,13 @@ namespace { // TODO: Proper panic handling, including scope destruction m_builder.set_cur_block(res__panic); + //m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() ); // TODO: Should this drop the value written to the rawptr? // - No, becuase it's likely invalid now. Goodbye! m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); m_builder.set_cur_block(res__ok); + m_builder.mark_value_assigned(node.span(), res); m_builder.set_result( node.span(), mv$(res) ); } @@ -1735,6 +1729,8 @@ namespace { m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); m_builder.set_cur_block( next_block ); + // TODO: Support diverging value calls + m_builder.mark_value_assigned(node.span(), res); m_builder.set_result( node.span(), mv$(res) ); } void visit(::HIR::ExprNode_CallMethod& node) override diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index 9ee7b733..2a5da9fe 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -195,9 +195,9 @@ public: // Mark a value as initialised (used for Call, because it has to be done after the panic block is populated) void mark_value_assigned(const Span& sp, const ::MIR::LValue& val); - // Moves control of temporaries up to the next scope - void raise_variables(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope); - void raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope); + // Moves control of temporaries up to the specified scope (or to above it) + void raise_variables(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope, bool to_above=false); + void raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope, bool to_above=false); void set_cur_block(unsigned int new_block); ::MIR::BasicBlockId pause_cur_block(); diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 54dbc5e7..e8392ef2 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -402,26 +402,31 @@ void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst) } } -void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope) +void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const ScopeHandle& scope, bool to_above/*=false*/) { TRACE_FUNCTION_F(val); TU_MATCH_DEF(::MIR::LValue, (val), (e), ( - // No raising of these source values + // No raising of these source values? return ; ), // TODO: This may not be correct, because it can change the drop points and ordering // HACK: Working around cases where values are dropped while the result is not yet used. + (Index, + raise_variables(sp, *e.val, scope, to_above); + raise_variables(sp, *e.idx, scope, to_above); + return ; + ), (Deref, - raise_variables(sp, *e.val, scope); + raise_variables(sp, *e.val, scope, to_above); return ; ), (Field, - raise_variables(sp, *e.val, scope); + raise_variables(sp, *e.val, scope, to_above); return ; ), (Downcast, - raise_variables(sp, *e.val, scope); + raise_variables(sp, *e.val, scope, to_above); return ; ), // Actual value types @@ -437,6 +442,11 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const { auto& scope_def = m_scopes.at(*scope_it); + if( *scope_it == scope.idx && !to_above ) + { + DEBUG(val << " defined in or above target (scope " << scope << ")"); + } + TU_IFLET( ScopeType, scope_def.data, Variables, e, if( const auto* ve = val.opt_Variable() ) { @@ -470,7 +480,10 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const } // If the variable was defined above the desired scope (i.e. this didn't find it), return if( *scope_it == scope.idx ) + { + DEBUG("Value " << val << " is defined above the target (scope " << scope << ")"); return ; + } ++scope_it; } if( scope_it == m_scope_stack.rend() ) @@ -479,7 +492,37 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const BUG(sp, val << " wasn't defined in a visible scope"); return ; } - ++scope_it; + + if( *scope_it == scope.idx ) + { + // Already hit the specified scope + if( to_above ) { + // Want to shift to any above (but not including) it + ++ scope_it; + } + else { + // Want to shift to it or above. + } + } + else + { + ++scope_it; + + while( scope_it != m_scope_stack.rend() ) + { + if( *scope_it == scope.idx ) + { + break ; + } + ++ scope_it; + } + } + if( scope_it == m_scope_stack.rend() ) + { + // Temporary wasn't defined in a visible scope? + BUG(sp, "Scope " << scope << " isn't on the stack"); + return ; + } while( scope_it != m_scope_stack.rend() ) { @@ -514,16 +557,17 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const } ++scope_it; } + BUG(sp, "Couldn't find a scope to raise " << val << " into"); } -void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope) +void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope, bool to_above/*=false*/) { auto raise_vars = [&](const ::MIR::Param& p) { if( const auto* e = p.opt_LValue() ) - this->raise_variables(sp, *e, scope); + this->raise_variables(sp, *e, scope, to_above); }; TU_MATCHA( (rval), (e), (Use, - this->raise_variables(sp, e, scope); + this->raise_variables(sp, e, scope, to_above); ), (Constant, ), @@ -532,23 +576,23 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, cons ), (Borrow, // TODO: Wait, is this valid? - this->raise_variables(sp, e.val, scope); + this->raise_variables(sp, e.val, scope, to_above); ), (Cast, - this->raise_variables(sp, e.val, scope); + this->raise_variables(sp, e.val, scope, to_above); ), (BinOp, raise_vars(e.val_l); raise_vars(e.val_r); ), (UniOp, - this->raise_variables(sp, e.val, scope); + this->raise_variables(sp, e.val, scope, to_above); ), (DstMeta, - this->raise_variables(sp, e.val, scope); + this->raise_variables(sp, e.val, scope, to_above); ), (DstPtr, - this->raise_variables(sp, e.val, scope); + this->raise_variables(sp, e.val, scope, to_above); ), (MakeDst, raise_vars(e.ptr_val); @@ -1130,10 +1174,10 @@ void MirBuilder::complete_scope(ScopeDef& sd) TU_MATCHA( (sd.data), (e), (Temporaries, - DEBUG("Temporaries " << e.temporaries); + DEBUG("Temporaries - " << e.temporaries); ), (Variables, - DEBUG("Variables " << e.vars); + DEBUG("Variables - " << e.vars); ), (Loop, DEBUG("Loop"); @@ -1574,6 +1618,7 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd) for(auto tmp_idx : ::reverse(e.temporaries)) { const auto& vs = get_temp_state(sd.span, tmp_idx); + DEBUG("tmp" << tmp_idx << " - " << vs); drop_value_from_state( sd.span, vs, ::MIR::LValue::make_Temporary({ tmp_idx }) ); } ), @@ -1581,6 +1626,7 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd) for(auto var_idx : ::reverse(e.vars)) { const auto& vs = get_variable_state(sd.span, var_idx); + DEBUG("var" << var_idx << " - " << vs); drop_value_from_state( sd.span, vs, ::MIR::LValue::make_Variable(var_idx) ); } ), @@ -1599,11 +1645,13 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv) TU_MATCHA( (lv), (e), (Variable, if( !lvalue_is_copy(sp, lv) ) { + DEBUG("var" << e << " = MOVED"); get_variable_state_mut(sp, e) = VarState::make_Invalid(InvalidType::Moved); } ), (Temporary, if( !lvalue_is_copy(sp, lv) ) { + DEBUG("tmp" << e.idx << " = MOVED"); get_temp_state_mut(sp, e.idx) = VarState::make_Invalid(InvalidType::Moved); } ), @@ -1665,9 +1713,11 @@ 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, + DEBUG("var" << ei << " = PARTIAL"); get_variable_state_mut(sp, ei) = VarState::make_Partial({ mv$(ivs) }); ), (Temporary, + DEBUG("tmp" << ei.idx << " = PARTIAL"); get_temp_state_mut(sp, ei.idx) = VarState::make_Partial({ mv$(ivs) }); ), (Argument, |