summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mir/from_hir.cpp25
-rw-r--r--src/mir/mir_builder.cpp146
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)
{