diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mir/from_hir.cpp | 25 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 146 |
2 files changed, 106 insertions, 65 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index a9a40b58..0f200d31 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -374,6 +374,8 @@ namespace { { bool diverged = false; + auto res_val = (node.m_yields_final ? m_builder.new_temporary(node.m_res_type) : ::MIR::LValue()); + auto tmp_scope = m_builder.new_scope_temp(node.span()); auto scope = m_builder.new_scope_var(node.span()); for(unsigned int i = 0; i < node.m_nodes.size() - (node.m_yields_final ? 1 : 0); i ++) @@ -416,7 +418,6 @@ namespace { auto& subnode = node.m_nodes.back(); const Span& sp = subnode->span(); - auto res_val = m_builder.new_temporary(node.m_res_type); auto stmt_scope = m_builder.new_scope_temp(sp); this->visit_node_ptr(subnode); if( m_builder.has_result() || m_builder.block_active() ) @@ -428,13 +429,15 @@ namespace { m_builder.push_stmt_assign(sp, res_val.clone(), m_builder.get_result(sp)); m_builder.terminate_scope(sp, mv$(stmt_scope)); - m_builder.terminate_scope( node.span(), mv$(scope) ); + m_builder.terminate_scope(node.span(), mv$(scope) ); + m_builder.terminate_scope(node.span(), mv$(tmp_scope) ); m_builder.set_result( node.span(), mv$(res_val) ); } else { - m_builder.terminate_scope( node.span(), mv$(stmt_scope), false ); + m_builder.terminate_scope( sp, mv$(stmt_scope), false ); m_builder.terminate_scope( node.span(), mv$(scope), false ); + m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); // Block diverged in final node. } } @@ -443,12 +446,14 @@ namespace { if( diverged ) { m_builder.terminate_scope( node.span(), mv$(scope), false ); + m_builder.terminate_scope( node.span(), mv$(tmp_scope), false ); m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); // Don't set a result if there's no block. } else { m_builder.terminate_scope( node.span(), mv$(scope) ); + m_builder.terminate_scope( node.span(), mv$(tmp_scope) ); m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({})); } } @@ -593,6 +598,7 @@ namespace { { TRACE_FUNCTION_FR("_Match", "_Match"); this->visit_node_ptr(node.m_value); + auto stmt_scope = m_builder.new_scope_temp(node.span()); auto match_val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type); if( node.m_arms.size() == 0 ) { @@ -635,6 +641,19 @@ namespace { else { MIR_LowerHIR_Match(m_builder, *this, node, mv$(match_val)); } + + if( m_builder.block_active() ) { + const auto& sp = node.span(); + + auto res = m_builder.get_result(sp); + m_builder.raise_variables(sp, res, stmt_scope); + m_builder.set_result(sp, mv$(res)); + + m_builder.terminate_scope( node.span(), mv$(stmt_scope) ); + } + else { + m_builder.terminate_scope( node.span(), mv$(stmt_scope), false ); + } } // ExprNode_Match void emit_if(/*const*/ ::HIR::ExprNodeP& cond, ::MIR::BasicBlockId true_branch, ::MIR::BasicBlockId false_branch) diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 1733df2f..987eb267 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -116,6 +116,22 @@ void MirBuilder::define_variable(unsigned int idx) top_scope = &m_scopes.at(idx); break ; } + else if( m_scopes.at(idx).data.is_Loop() ) + { + // Newly created temporary within a loop, if there is a saved + // state this temp needs a drop flag. + // TODO: ^ + } + else if( m_scopes.at(idx).data.is_Split() ) + { + // Newly created temporary within a split, if there is a saved + // state this temp needs a drop flag. + // TODO: ^ + } + else + { + // Nothign. + } } assert( top_scope ); auto& tmp_scope = top_scope->data.as_Temporaries(); @@ -396,22 +412,33 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const // HACK: Working around cases where values are dropped while the result is not yet used. (Deref, raise_variables(sp, *e.val, scope); + return ; ), (Field, raise_variables(sp, *e.val, scope); + return ; ), (Downcast, raise_variables(sp, *e.val, scope); + return ; ), // Actual value types (Variable, - auto idx = e; - auto scope_it = m_scope_stack.rbegin(); - while( scope_it != m_scope_stack.rend() ) - { - auto& scope_def = m_scopes.at(*scope_it); + ), + (Temporary, + ) + ) + ASSERT_BUG(sp, val.is_Variable() || val.is_Temporary(), ""); - TU_IFLET( ScopeType, scope_def.data, Variables, e, + auto scope_it = m_scope_stack.rbegin(); + while( scope_it != m_scope_stack.rend() ) + { + auto& scope_def = m_scopes.at(*scope_it); + + TU_IFLET( ScopeType, scope_def.data, Variables, e, + if( const auto* ve = val.opt_Variable() ) + { + auto idx = *ve; auto tmp_it = ::std::find( e.vars.begin(), e.vars.end(), idx ); if( tmp_it != e.vars.end() ) { @@ -419,41 +446,12 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const DEBUG("Raise variable " << idx << " from " << *scope_it); break ; } - ) - // If the variable was defined above the desired scope (i.e. this didn't find it), return - if( *scope_it == scope.idx ) - return ; - ++scope_it; - } - if( scope_it == m_scope_stack.rend() ) - { - // Temporary wasn't defined in a visible scope? - return ; - } - ++scope_it; - - while( scope_it != m_scope_stack.rend() ) - { - auto& scope_def = m_scopes.at(*scope_it); - - TU_IFLET( ScopeType, scope_def.data, Variables, e, - e.vars.push_back( idx ); - DEBUG("- to " << *scope_it); - return ; - ) - ++scope_it; - } - - DEBUG("- top"); - ), - (Temporary, - auto idx = e.idx; - auto scope_it = m_scope_stack.rbegin(); - while( scope_it != m_scope_stack.rend() ) - { - auto& scope_def = m_scopes.at(*scope_it); - - TU_IFLET( ScopeType, scope_def.data, Temporaries, e, + } + ) + else TU_IFLET( ScopeType, scope_def.data, Temporaries, e, + if( const auto* ve = val.opt_Temporary() ) + { + auto idx = ve->idx; auto tmp_it = ::std::find( e.temporaries.begin(), e.temporaries.end(), idx ); if( tmp_it != e.temporaries.end() ) { @@ -461,35 +459,59 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const DEBUG("Raise temporary " << idx << " from " << *scope_it); break ; } - ) - - // If the temporary was defined above the desired scope (i.e. this didn't find it), return - if( *scope_it == scope.idx ) - return ; - ++scope_it; - } - if( scope_it == m_scope_stack.rend() ) + } + ) + else { - // Temporary wasn't defined in a visible scope? - return ; + // TODO: Does this need to handle this value being set in the + // split scopes? } + // If the variable was defined above the desired scope (i.e. this didn't find it), return + if( *scope_it == scope.idx ) + return ; ++scope_it; + } + if( scope_it == m_scope_stack.rend() ) + { + // Temporary wasn't defined in a visible scope? + BUG(sp, val << " wasn't defined in a visible scope"); + return ; + } + ++scope_it; - while( scope_it != m_scope_stack.rend() ) - { - auto& scope_def = m_scopes.at(*scope_it); + while( scope_it != m_scope_stack.rend() ) + { + auto& scope_def = m_scopes.at(*scope_it); - TU_IFLET( ScopeType, scope_def.data, Temporaries, e, - e.temporaries.push_back( idx ); + TU_IFLET( ScopeType, scope_def.data, Variables, e, + if( const auto* ve = val.opt_Variable() ) + { + e.vars.push_back( *ve ); DEBUG("- to " << *scope_it); return ; - ) - ++scope_it; - } - - DEBUG("- top"); + } ) - ) + else TU_IFLET( ScopeType, scope_def.data, Temporaries, e, + if( const auto* ve = val.opt_Temporary() ) + { + e.temporaries.push_back( ve->idx ); + DEBUG("- to " << *scope_it); + return ; + } + ) + else if( scope_def.data.is_Loop() ) + { + //TODO(sp, "Raising " << val << " to outside of a loop"); + } + else if( scope_def.data.is_Split() ) + { + //TODO(sp, "Raising " << val << " to outside of a split"); + } + else + { + } + ++scope_it; + } } void MirBuilder::raise_variables(const Span& sp, const ::MIR::RValue& rval, const ScopeHandle& scope) { |