summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mir/from_hir.cpp15
-rw-r--r--src/mir/mir_builder.cpp45
2 files changed, 49 insertions, 11 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index a15ea8ef..df48627f 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -409,9 +409,9 @@ namespace {
bool diverged = false;
auto res_val = (node.m_yields_final ? m_builder.new_temporary(node.m_res_type) : ::MIR::LValue());
+ auto scope = m_builder.new_scope_var(node.span());
auto tmp_scope = m_builder.new_scope_temp(node.span());
auto _block_tmp_scope = save_and_edit(m_block_tmp_scope, &tmp_scope);
- 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 ++)
{
@@ -452,15 +452,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$(tmp_scope) );
+ m_builder.terminate_scope(node.span(), mv$(scope) );
m_builder.set_result( node.span(), mv$(res_val) );
}
else
{
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 );
+ m_builder.terminate_scope( node.span(), mv$(scope), false );
// Block diverged in final node.
}
}
@@ -468,15 +468,15 @@ namespace {
{
if( diverged )
{
- m_builder.terminate_scope( node.span(), mv$(scope), false );
m_builder.terminate_scope( node.span(), mv$(tmp_scope), false );
+ m_builder.terminate_scope( node.span(), mv$(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.terminate_scope( node.span(), mv$(scope) );
m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
}
@@ -1990,6 +1990,7 @@ namespace {
::MIR::LValue base_val;
if( node.m_base_value )
{
+ DEBUG("_StructLiteral - base");
this->visit_node_ptr(node.m_base_value);
base_val = m_builder.get_result_in_lvalue(node.m_base_value->span(), node.m_base_value->m_res_type);
}
@@ -2028,6 +2029,7 @@ namespace {
auto idx = ::std::find_if(fields.begin(), fields.end(), [&](const auto&x){ return x.first == ent.first; }) - fields.begin();
assert( !values_set[idx] );
values_set[idx] = true;
+ DEBUG("_StructLiteral - fld '" << ent.first << "' (idx " << idx << ")");
this->visit_node_ptr(valnode);
auto res = m_builder.get_result(valnode->span());
@@ -2128,6 +2130,7 @@ namespace {
void visit(::HIR::ExprNode_Closure& node) override
{
TRACE_FUNCTION_F("_Closure - " << node.m_obj_path);
+ auto _ = save_and_edit(m_borrow_raise_target, nullptr);
::std::vector< ::MIR::Param> vals;
vals.reserve( node.m_captures.size() );
@@ -2175,6 +2178,8 @@ namespace {
root_node.visit( ev );
}
+ MIR_Validate(resolve, path, fcn, args, ptr->m_res_type);
+
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index e8392ef2..96bb28b3 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -544,13 +544,46 @@ void MirBuilder::raise_variables(const Span& sp, const ::MIR::LValue& val, const
return ;
}
)
- else if( scope_def.data.is_Loop() )
+ else if( auto* sd_loop = scope_def.data.opt_Loop() )
{
- //TODO(sp, "Raising " << val << " to outside of a loop");
+ // If there is an exit state present, ensure that this variable is
+ // present in that state (as invalid, as it can't have been valid
+ // externally)
+ if( sd_loop->exit_state_valid )
+ {
+ DEBUG("Adding " << val << " as unset to loop exit state");
+ if( const auto* ve = val.opt_Variable() )
+ {
+ auto v = sd_loop->exit_state.var_states.insert( ::std::make_pair(*ve, VarState(InvalidType::Uninit)) );
+ ASSERT_BUG(sp, v.second, "Raising " << val << " which already had a state entry");
+ }
+ else if( const auto* ve = val.opt_Temporary() )
+ {
+ auto v = sd_loop->exit_state.tmp_states.insert( ::std::make_pair(ve->idx, VarState(InvalidType::Uninit)) );
+ ASSERT_BUG(sp, v.second, "Raising " << val << " which already had a state entry");
+ }
+ else {
+ BUG(sp, "Impossible raise value");
+ }
+ }
+ else
+ {
+ DEBUG("Crossing loop with no existing exit state");
+ }
}
else if( scope_def.data.is_Split() )
{
- //TODO(sp, "Raising " << val << " to outside of a split");
+ auto& sd_split = scope_def.data.as_Split();
+ // If the split has already registered an exit state, ensure that
+ // this variable is present in it. (as invalid)
+ if( sd_split.end_state_valid )
+ {
+ TODO(sp, "Raising " << val << " to outside of a split");
+ }
+ else
+ {
+ DEBUG("Crossing split with no existing end state");
+ }
}
else
{
@@ -1065,11 +1098,11 @@ void MirBuilder::terminate_loop_early(const Span& sp, ScopeType::Data_Loop& sd_l
void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool reachable)
{
- ASSERT_BUG(sp, handle.idx < m_scopes.size(), "");
+ ASSERT_BUG(sp, handle.idx < m_scopes.size(), "Handle passed to end_split_arm is invalid");
auto& sd = m_scopes.at( handle.idx );
- ASSERT_BUG(sp, sd.data.is_Split(), "");
+ ASSERT_BUG(sp, sd.data.is_Split(), "Ending split arm on non-Split arm - " << sd.data.tag_str());
auto& sd_split = sd.data.as_Split();
- ASSERT_BUG(sp, !sd_split.arms.empty(), "");
+ ASSERT_BUG(sp, !sd_split.arms.empty(), "Split arm list is empty (impossible)");
TRACE_FUNCTION_F("end split scope " << handle.idx << " arm " << (sd_split.arms.size()-1));
if( reachable )