diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/helpers.cpp | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp index 72abf10d..237e1f56 100644 --- a/src/mir/helpers.cpp +++ b/src/mir/helpers.cpp @@ -405,8 +405,7 @@ namespace { (SetDropFlag, ), (Drop, - // Well, it mutates... - rv |= visit_mir_lvalue(e.slot, ValUsage::Write, cb); + rv |= visit_mir_lvalue(e.slot, ValUsage::Move, cb); ), (ScopeEnd, ) @@ -416,7 +415,7 @@ namespace { bool visit_mir_lvalues(const ::MIR::Terminator& term, ::std::function<bool(const ::MIR::LValue& , ValUsage)> cb) { - bool rv = true; + bool rv = false; TU_MATCHA( (term), (e), (Incomplete, ), @@ -429,10 +428,10 @@ namespace { (Panic, ), (If, - return visit_mir_lvalue(e.cond, ValUsage::Read, cb); + rv |= visit_mir_lvalue(e.cond, ValUsage::Read, cb); ), (Switch, - return visit_mir_lvalue(e.val, ValUsage::Read, cb); + rv |= visit_mir_lvalue(e.val, ValUsage::Read, cb); ), (Call, if( e.fcn.is_Value() ) { @@ -930,10 +929,10 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime( { for(const auto& stmt : bb.statements) { - use_bitmap[pos] = visit_mir_lvalues(stmt, [&](const ::MIR::LValue& tlv, auto _){ return tlv == lv; }); + use_bitmap[pos] = visit_mir_lvalues(stmt, [&](const ::MIR::LValue& tlv, auto vu){ return tlv == lv && vu != ValUsage::Write; }); pos ++; } - use_bitmap[pos] = visit_mir_lvalues(bb.terminator, [&](const ::MIR::LValue& tlv, auto _){ return tlv == lv; }); + use_bitmap[pos] = visit_mir_lvalues(bb.terminator, [&](const ::MIR::LValue& tlv, auto vu){ return tlv == lv && vu != ValUsage::Write; }); pos ++; } } @@ -959,14 +958,10 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime( // If the loop point is before the last recorded read, fill validity along the rest. if( static_cast<size_t>(it - state.bb_history.begin()) <= state.last_read_bb ) { - state.bb_history.push_back(bb_idx); - state.mark_read(0); DEBUG("Looped (before last read)"); } else if( vl.stmt_bitmap.at( block_offsets.at(bb_idx) + 0) ) { - state.bb_history.push_back(bb_idx); - state.mark_read(0); DEBUG("Looped (to already valid)"); } else @@ -977,6 +972,8 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime( post_check_list.push_back( ::std::make_pair(bb_idx, mv$(state)) ); continue ; } + state.bb_history.push_back(bb_idx); + state.mark_read(0); runner.apply_state(state, 0); continue ; @@ -987,6 +984,34 @@ void MIR_Helper_GetLifetimes_DetermineValueLifetime( // - Also, we don't want to give up early (if we loop back to the start of the first block) // - A per-statement bitmap would solve this. Return early if `!vl.stmt_bitmap & usage_stmt_bitmap == 0` // > Requires filling the bitmap as we go (for maximum efficiency) + { + bool found_non_visited = false; + for(size_t i = 0; i < use_bitmap.size(); i ++) + { + // If a place where the value is used is not present in the output bitmap + if( !vl.stmt_bitmap[i] && use_bitmap[i] ) + { + DEBUG("- Still used at +" << i); + found_non_visited = true; + } + } + // If there were no uses of the variable that aren't covered by the lifetime bitmap + if( ! found_non_visited ) + { + // Terminate early + DEBUG("Early terminate - All possible lifetimes covered"); + if(state.is_borrowed()) + state.bb_history.push_back(bb_idx); + runner.apply_state(state, 0); + for(auto& s : runner.m_states_to_do) + { + if(s.second.is_borrowed()) + s.second.bb_history.push_back(bb_idx); + runner.apply_state(s.second, 0); + } + return ; + } + } // Search for this block in any other state's history. // - If found, put this block on the "check later" list and move on. |