summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-08-23 18:12:43 +0800
committerJohn Hodge <tpg@mutabah.net>2016-08-23 18:12:43 +0800
commit4753c7fef99fdf2f483c331a1c6bc62b8813bb7e (patch)
tree06a24c20b39072301a77e138227683bc6a1571c4
parentc2aedab7b60ca3e6c293b7d022897aee0661db21 (diff)
downloadmrust-4753c7fef99fdf2f483c331a1c6bc62b8813bb7e.tar.gz
MIR Gen - Span information in assign/drop
-rw-r--r--src/mir/from_hir.cpp119
-rw-r--r--src/mir/from_hir.hpp24
-rw-r--r--src/mir/from_hir_match.cpp38
-rw-r--r--src/mir/mir_builder.cpp52
4 files changed, 131 insertions, 102 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 49dc0974..de90d789 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -132,15 +132,15 @@ namespace {
switch( pat.m_binding.m_type )
{
case ::HIR::PatternBinding::Type::Move:
- m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) );
+ m_builder.push_stmt_assign( sp, ::MIR::LValue::make_Variable(pat.m_binding.m_slot), mv$(lval) );
break;
case ::HIR::PatternBinding::Type::Ref:
- m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), ::MIR::RValue::make_Borrow({
+ m_builder.push_stmt_assign( sp, ::MIR::LValue::make_Variable(pat.m_binding.m_slot), ::MIR::RValue::make_Borrow({
0, ::HIR::BorrowType::Shared, mv$(lval)
}) );
break;
case ::HIR::PatternBinding::Type::MutRef:
- m_builder.push_stmt_assign( ::MIR::LValue::make_Variable(pat.m_binding.m_slot), ::MIR::RValue::make_Borrow({
+ m_builder.push_stmt_assign( sp, ::MIR::LValue::make_Variable(pat.m_binding.m_slot), ::MIR::RValue::make_Borrow({
0, ::HIR::BorrowType::Unique, mv$(lval)
}) );
break;
@@ -266,7 +266,7 @@ namespace {
auto stmt_scope = m_builder.new_scope_temp(sp);
this->visit_node_ptr(subnode);
if( m_builder.has_result() || m_builder.block_active() ) {
- m_builder.push_stmt_assign( res.clone(), m_builder.get_result(sp) );
+ m_builder.push_stmt_assign( sp, res.clone(), m_builder.get_result(sp) );
m_builder.terminate_scope(sp, mv$(stmt_scope));
res_valid = true;
}
@@ -299,8 +299,7 @@ namespace {
TRACE_FUNCTION_F("_Return");
this->visit_node_ptr(node.m_value);
- m_builder.push_stmt_assign( ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) );
- // TODO: Insert drop of all current scopes
+ m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Return({}), m_builder.get_result(node.span()) );
m_builder.terminate_scope_early( node.span(), m_builder.fcn_scope() );
m_builder.end_block( ::MIR::Terminator::make_Return({}) );
}
@@ -312,7 +311,7 @@ namespace {
{
this->visit_node_ptr(node.m_value);
- this->destructure_from(node.span(), node.m_pattern, m_builder.lvalue_or_temp(node.m_type, m_builder.get_result(node.span()) ));
+ this->destructure_from(node.span(), node.m_pattern, m_builder.get_result_in_lvalue(node.m_value->span(), node.m_type));
}
m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
@@ -374,7 +373,7 @@ namespace {
{
TRACE_FUNCTION_F("_Match");
this->visit_node_ptr(node.m_value);
- auto match_val = m_builder.lvalue_or_temp(node.m_value->m_res_type, m_builder.get_result(node.m_value->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 ) {
// Nothing
@@ -403,7 +402,7 @@ namespace {
TRACE_FUNCTION_F("_If");
this->visit_node_ptr(node.m_cond);
- auto decision_val = m_builder.lvalue_or_temp(node.m_cond->m_res_type, m_builder.get_result(node.m_cond->span()) );
+ auto decision_val = m_builder.get_result_in_lvalue(node.m_cond->span(), node.m_cond->m_res_type);
auto true_branch = m_builder.new_bb_unlinked();
auto false_branch = m_builder.new_bb_unlinked();
@@ -420,7 +419,7 @@ namespace {
m_builder.set_cur_block(true_branch);
this->visit_node_ptr(node.m_true);
if( m_builder.block_active() || m_builder.has_result() ) {
- m_builder.push_stmt_assign( result_val.clone(), m_builder.get_result(node.m_true->span()) );
+ m_builder.push_stmt_assign( node.span(), result_val.clone(), m_builder.get_result(node.m_true->span()) );
m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) );
m_builder.end_split_arm(node.span(), scope, true);
}
@@ -436,7 +435,7 @@ namespace {
this->visit_node_ptr(node.m_false);
if( m_builder.block_active() )
{
- m_builder.push_stmt_assign( result_val.clone(), m_builder.get_result(node.m_false->span()) );
+ m_builder.push_stmt_assign( node.span(), result_val.clone(), m_builder.get_result(node.m_false->span()) );
m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) );
m_builder.end_split_arm(node.span(), scope, true);
}
@@ -447,7 +446,7 @@ namespace {
else
{
// Assign `()` to the result
- m_builder.push_stmt_assign( result_val.clone(), ::MIR::RValue::make_Tuple({}) );
+ m_builder.push_stmt_assign(node.span(), result_val.clone(), ::MIR::RValue::make_Tuple({}) );
m_builder.end_block( ::MIR::Terminator::make_Goto(next_block) );
m_builder.end_split_arm(node.span(), scope, true);
}
@@ -480,7 +479,7 @@ namespace {
}
)
)
- m_builder.push_stmt_assign(mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
+ m_builder.push_stmt_assign(sp, mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
break;
// Bitwise masking operations: Require equal integer types or bool
case ::MIR::eBinOp::BIT_XOR:
@@ -498,7 +497,7 @@ namespace {
default:
break;
}
- m_builder.push_stmt_assign(mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
+ m_builder.push_stmt_assign(sp, mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
break;
case ::MIR::eBinOp::ADD: case ::MIR::eBinOp::ADD_OV:
case ::MIR::eBinOp::SUB: case ::MIR::eBinOp::SUB_OV:
@@ -517,7 +516,7 @@ namespace {
break;
}
// TODO: Overflow checks (none for eBinOp::MOD)
- m_builder.push_stmt_assign(mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
+ m_builder.push_stmt_assign(sp, mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
break;
case ::MIR::eBinOp::BIT_SHL:
case ::MIR::eBinOp::BIT_SHR:
@@ -545,7 +544,7 @@ namespace {
break;
}
// TODO: Overflow check
- m_builder.push_stmt_assign(mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
+ m_builder.push_stmt_assign(sp, mv$(res_slot), ::MIR::RValue::make_BinOp({ mv$(val_l), op, mv$(val_r) }));
break;
}
}
@@ -556,10 +555,10 @@ namespace {
const auto& sp = node.span();
this->visit_node_ptr(node.m_value);
- auto val = m_builder.get_result(sp);
+ ::MIR::RValue val = m_builder.get_result(sp);
this->visit_node_ptr(node.m_slot);
- auto dst = m_builder.get_result_lvalue(sp);
+ auto dst = m_builder.get_result_unwrap_lvalue(sp);
const auto& ty_slot = node.m_slot->m_res_type;
const auto& ty_val = node.m_value->m_res_type;
@@ -567,7 +566,7 @@ namespace {
if( node.m_op != ::HIR::ExprNode_Assign::Op::None )
{
auto dst_clone = dst.clone();
- auto val_lv = m_builder.lvalue_or_temp( ty_val, mv$(val) );
+ auto val_lv = m_builder.lvalue_or_temp( node.span(), ty_val, mv$(val) );
ASSERT_BUG(sp, ty_slot.m_data.is_Primitive(), "Assignment operator overloads are only valid on primitives - ty_slot="<<ty_slot);
ASSERT_BUG(sp, ty_val.m_data.is_Primitive(), "Assignment operator overloads are only valid on primitives - ty_val="<<ty_val);
@@ -602,7 +601,7 @@ namespace {
else
{
ASSERT_BUG(sp, ty_slot == ty_val, "Types must match for assignment - " << ty_slot << " != " << ty_val);
- m_builder.push_stmt_assign(mv$(dst), mv$(val));
+ m_builder.push_stmt_assign(node.span(), mv$(dst), mv$(val));
}
m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
@@ -614,11 +613,11 @@ namespace {
const auto& ty_l = node.m_left->m_res_type;
this->visit_node_ptr(node.m_left);
- auto left = m_builder.lvalue_or_temp( ty_l, m_builder.get_result(node.m_left->span()) );
+ auto left = m_builder.get_result_in_lvalue(node.m_left->span(), ty_l);
const auto& ty_r = node.m_right->m_res_type;
this->visit_node_ptr(node.m_right);
- auto right = m_builder.lvalue_or_temp( ty_r, m_builder.get_result(node.m_right->span()) );
+ auto right = m_builder.get_result_in_lvalue(node.m_right->span(), ty_r);
auto res = m_builder.new_temporary(node.m_res_type);
::MIR::eBinOp op;
@@ -659,12 +658,12 @@ namespace {
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(left), bb_true, bb_false }) );
// If left is false, assign result false and return
m_builder.set_cur_block( bb_false );
- m_builder.push_stmt_assign(res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(false) ));
+ m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(false) ));
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
// If left is true, assign result to right
m_builder.set_cur_block( bb_true );
- m_builder.push_stmt_assign(res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
+ m_builder.push_stmt_assign(node.span(), res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
m_builder.set_cur_block( bb_next );
@@ -676,12 +675,12 @@ namespace {
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(left), bb_true, bb_false }) );
// If left is true, assign result true and return
m_builder.set_cur_block( bb_true );
- m_builder.push_stmt_assign(res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(true) ));
+ m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue( ::MIR::Constant::make_Bool(true) ));
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
// If left is false, assign result to right
m_builder.set_cur_block( bb_false );
- m_builder.push_stmt_assign(res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
+ m_builder.push_stmt_assign(node.span(), res.clone(), mv$(right)); // TODO: Right doens't need to be an LValue here.
m_builder.end_block( ::MIR::Terminator::make_Goto(bb_next) );
m_builder.set_cur_block( bb_next );
@@ -696,9 +695,9 @@ namespace {
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
- auto val = m_builder.lvalue_or_temp( ty_val, m_builder.get_result(node.m_value->span()) );
+ auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
- auto res = m_builder.new_temporary(node.m_res_type);
+ ::MIR::RValue res;
switch(node.m_op)
{
case ::HIR::ExprNode_UniOp::Op::Invert:
@@ -718,7 +717,7 @@ namespace {
else {
BUG(node.span(), "`!` operator on invalid type - " << ty_val);
}
- m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::INV }));
+ res = ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::INV });
break;
case ::HIR::ExprNode_UniOp::Op::Negate:
if( ty_val.m_data.is_Primitive() ) {
@@ -743,7 +742,7 @@ namespace {
else {
BUG(node.span(), "`!` operator on invalid type - " << ty_val);
}
- m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::NEG }));
+ res = ::MIR::RValue::make_UniOp({ mv$(val), ::MIR::eUniOp::NEG });
break;
}
m_builder.set_result( node.span(), mv$(res) );
@@ -754,17 +753,17 @@ namespace {
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
- auto val = m_builder.lvalue_or_temp( ty_val, m_builder.get_result(node.m_value->span()) );
+ auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
auto res = m_builder.new_temporary(node.m_res_type);
- m_builder.push_stmt_assign(res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, node.m_type, mv$(val) }));
+ m_builder.push_stmt_assign( node.span(), res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, node.m_type, mv$(val) }));
m_builder.set_result( node.span(), mv$(res) );
}
void visit(::HIR::ExprNode_Cast& node) override
{
TRACE_FUNCTION_F("_Cast");
this->visit_node_ptr(node.m_value);
- auto val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) );
+ auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
@@ -865,14 +864,14 @@ namespace {
)
)
auto res = m_builder.new_temporary(node.m_res_type);
- m_builder.push_stmt_assign(res.clone(), ::MIR::RValue::make_Cast({ mv$(val), node.m_res_type.clone() }));
+ m_builder.push_stmt_assign(node.span(), res.clone(), ::MIR::RValue::make_Cast({ mv$(val), node.m_res_type.clone() }));
m_builder.set_result( node.span(), mv$(res) );
}
void visit(::HIR::ExprNode_Unsize& node) override
{
TRACE_FUNCTION_F("_Unsize");
this->visit_node_ptr(node.m_value);
- auto ptr_lval = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.span()) );
+ auto ptr_lval = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
@@ -889,14 +888,14 @@ namespace {
if( ty_in.m_data.is_Array() )
{
const auto& in_array = ty_in.m_data.as_Array();
- auto size_lval = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::Constant( static_cast<uint64_t>(in_array.size_val) ) );
+ auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::Constant( static_cast<uint64_t>(in_array.size_val) ) );
m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
}
else if( ty_in.m_data.is_Generic() )
{
// HACK: FixedSizeArray uses `A: Unsize<[T]>` which will lead to the above code not working (as the size isn't known).
// - Maybe _Meta on the `&A` would work as a stopgap (since A: Sized, it won't collide with &[T] or similar)
- auto size_lval = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ptr_lval.clone() }) );
+ auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ptr_lval.clone() }) );
m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
}
else
@@ -911,6 +910,7 @@ namespace {
::HIR::Path vtable { ty_in.clone(), e.m_trait.m_path.clone(), "#vtable" };
::HIR::TypeRef vtable_type { {} };
auto vtable_lval = m_builder.lvalue_or_temp(
+ node.span(),
::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, mv$(vtable_type)),
::MIR::RValue( ::MIR::Constant::make_ItemAddr(mv$(vtable)) )
);
@@ -926,11 +926,11 @@ namespace {
// NOTE: Calculate the index first (so if it borrows from the source, it's over by the time that's needed)
const auto& ty_idx = node.m_index->m_res_type;
this->visit_node_ptr(node.m_index);
- auto index = m_builder.lvalue_or_temp( ty_idx, m_builder.get_result(node.m_index->span()) );
+ auto index = m_builder.get_result_in_lvalue(node.m_index->span(), ty_idx);
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
- auto value = m_builder.lvalue_or_temp( ty_val, m_builder.get_result(node.m_value->span()) );
+ auto value = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
::MIR::RValue limit_val;
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_val.m_data), (e),
@@ -959,10 +959,10 @@ namespace {
// Range checking (DISABLED)
if( false )
{
- auto limit_lval = m_builder.lvalue_or_temp(node.m_index->m_res_type, mv$(limit_val));
+ auto limit_lval = m_builder.lvalue_or_temp( node.span(), ty_idx, mv$(limit_val) );
auto cmp_res = m_builder.new_temporary( ::HIR::CoreType::Bool );
- m_builder.push_stmt_assign(cmp_res.clone(), ::MIR::RValue::make_BinOp({ index.clone(), ::MIR::eBinOp::GE, mv$(limit_lval) }));
+ m_builder.push_stmt_assign(node.span(), cmp_res.clone(), ::MIR::RValue::make_BinOp({ index.clone(), ::MIR::eBinOp::GE, mv$(limit_lval) }));
auto arm_panic = m_builder.new_bb_unlinked();
auto arm_continue = m_builder.new_bb_unlinked();
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_res), arm_panic, arm_continue }) );
@@ -985,7 +985,7 @@ namespace {
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
- auto val = m_builder.lvalue_or_temp( ty_val, m_builder.get_result(node.m_value->span()) );
+ auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_val.m_data), (te),
(
@@ -1010,7 +1010,7 @@ namespace {
for(auto& arg : node.m_args)
{
this->visit_node_ptr(arg);
- values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
@@ -1027,7 +1027,7 @@ namespace {
for(auto& arg : node.m_args)
{
this->visit_node_ptr(arg);
- values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
@@ -1043,7 +1043,7 @@ namespace {
fcn_ty_data.m_arg_types.push_back( node.m_cache.m_arg_types[i].clone() );
}
auto fcn_val = m_builder.new_temporary( ::HIR::TypeRef(mv$(fcn_ty_data)) );
- m_builder.push_stmt_assign( fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(node.m_path.clone()) ) );
+ m_builder.push_stmt_assign( node.span(), fcn_val.clone(), ::MIR::RValue::make_Constant( ::MIR::Constant(node.m_path.clone()) ) );
auto panic_block = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
@@ -1069,14 +1069,14 @@ namespace {
// _CallValue is ONLY valid on function pointers (all others must be desugared)
ASSERT_BUG(node.span(), node.m_value->m_res_type.m_data.is_Function(), "Leftover _CallValue on a non-fn()");
this->visit_node_ptr(node.m_value);
- auto fcn_val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) );
+ auto fcn_val = m_builder.get_result_in_lvalue( node.m_value->span(), node.m_value->m_res_type );
::std::vector< ::MIR::LValue> values;
values.reserve( node.m_args.size() );
for(auto& arg : node.m_args)
{
this->visit_node_ptr(arg);
- values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
@@ -1106,7 +1106,9 @@ namespace {
{
TRACE_FUNCTION_F("_Field");
this->visit_node_ptr(node.m_value);
- auto val = m_builder.get_result_lvalue(node.m_value->span());
+ // TODO: What if this is called as `(1, 2, 3).0`
+ // - NOTE: `rustc` accepts the above - even for assignments. So `get_result_in_lvalue` is likely more correct
+ auto val = m_builder.get_result_unwrap_lvalue(node.m_value->span());
unsigned int idx;
if( '0' <= node.m_field[0] && node.m_field[0] <= '9' ) {
@@ -1183,7 +1185,7 @@ namespace {
),
(Constant,
auto tmp = m_builder.new_temporary( e.m_type );
- m_builder.push_stmt_assign( tmp.clone(), ::MIR::Constant::make_Const({node.m_path.clone()}) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({node.m_path.clone()}) );
m_builder.set_result( node.span(), mv$(tmp) );
),
(Static,
@@ -1206,8 +1208,8 @@ namespace {
fcn_ty_data.m_arg_types.push_back( monomorphise_type(sp, e.m_params, pe.m_params, arg.second) );
}
auto tmp = m_builder.new_temporary( ::HIR::TypeRef( mv$(fcn_ty_data) ) );
- m_builder.push_stmt_assign( tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
- m_builder.set_result( node.span(), mv$(tmp) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
+ m_builder.set_result( sp, mv$(tmp) );
),
(StructConstructor,
BUG(sp, "StructConstructor as PathValue");
@@ -1238,7 +1240,7 @@ namespace {
if( node.m_base_value )
{
this->visit_node_ptr(node.m_base_value);
- base_val = m_builder.get_result_lvalue(node.m_base_value->span());
+ base_val = m_builder.get_result_in_lvalue(node.m_base_value->span(), node.m_base_value->m_res_type);
}
const ::HIR::t_struct_fields* fields_ptr = nullptr;
@@ -1266,11 +1268,12 @@ namespace {
for(auto& ent : node.m_values)
{
+ auto& valnode = ent.second;
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;
- this->visit_node_ptr(ent.second);
- values.at(idx) = m_builder.lvalue_or_temp( ent.second->m_res_type, m_builder.get_result(ent.second->span()) );
+ this->visit_node_ptr(valnode);
+ values.at(idx) = m_builder.lvalue_or_temp( valnode->span(), valnode->m_res_type, m_builder.get_result(valnode->span()) );
}
for(unsigned int i = 0; i < values.size(); i ++)
{
@@ -1299,7 +1302,7 @@ namespace {
for(auto& arg : node.m_vals)
{
this->visit_node_ptr(arg);
- values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) );
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({
@@ -1315,7 +1318,7 @@ namespace {
for(auto& arg : node.m_vals)
{
this->visit_node_ptr(arg);
- values.push_back( m_builder.lvalue_or_temp( arg->m_res_type, m_builder.get_result(arg->span()) ) );
+ values.push_back( m_builder.lvalue_or_temp( arg->span(), arg->m_res_type, m_builder.get_result(arg->span()) ) );
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Array({
@@ -1327,7 +1330,7 @@ namespace {
{
TRACE_FUNCTION_F("_ArraySized");
this->visit_node_ptr( node.m_val );
- auto value = m_builder.lvalue_or_temp( node.m_val->m_res_type, m_builder.get_result(node.m_val->span()) );
+ auto value = m_builder.lvalue_or_temp( node.span(), node.m_val->m_res_type, m_builder.get_result(node.m_val->span()) );
m_builder.set_result( node.span(), ::MIR::RValue::make_SizedArray({
mv$(value),
@@ -1349,7 +1352,7 @@ namespace {
}
else {
auto borrow_ty = ::HIR::BorrowType::Shared;
- auto lval = m_builder.lvalue_or_temp(
+ auto lval = m_builder.lvalue_or_temp( node.span(),
::HIR::TypeRef::new_borrow(borrow_ty, m_variable_types[cap_idx].clone()),
::MIR::RValue::make_Borrow({ 0, borrow_ty, ::MIR::LValue::make_Variable(cap_idx) })
);
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index 3fd3c055..3889c654 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -89,8 +89,19 @@ class MirBuilder
struct ScopeDef
{
+ const Span& span;
bool complete = false;
ScopeType data;
+
+ ScopeDef(const Span& span):
+ span(span)
+ {
+ }
+ ScopeDef(const Span& span, ScopeType data):
+ span(span),
+ data(mv$(data))
+ {
+ }
};
::std::vector<ScopeDef> m_scopes;
@@ -104,20 +115,23 @@ public:
// - Values
::MIR::LValue new_temporary(const ::HIR::TypeRef& ty);
- ::MIR::LValue lvalue_or_temp(const ::HIR::TypeRef& ty, ::MIR::RValue val);
+ ::MIR::LValue lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val);
bool has_result() const {
return m_result_valid;
}
- ::MIR::RValue get_result(const Span& sp);
- ::MIR::LValue get_result_lvalue(const Span& sp);
void set_result(const Span& sp, ::MIR::RValue val);
+ ::MIR::RValue get_result(const Span& sp);
+ /// Obtains the result, unwrapping into a LValue (and erroring if not)
+ ::MIR::LValue get_result_unwrap_lvalue(const Span& sp);
+ /// Obtains the result, copying into a temporary if required
+ ::MIR::LValue get_result_in_lvalue(const Span& sp, const ::HIR::TypeRef& ty);
// - Statements
// Push an assignment. NOTE: This also marks the rvalue as moved
- void push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val);
+ void push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val);
// Push a drop (likely only used by scope cleanup)
- void push_stmt_drop(::MIR::LValue val);
+ void push_stmt_drop(const Span& sp, ::MIR::LValue val);
// - Block management
bool block_active() const {
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index 3ad3a11b..1f087da8 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -136,7 +136,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
builder.set_cur_block( ac.cond_start );
conv.visit_node_ptr( arm.m_cond );
- ac.cond_lval = builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Bool), builder.get_result(arm.m_cond->span()) );
+ ac.cond_lval = builder.get_result_in_lvalue(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool));
ac.cond_end = builder.pause_cur_block();
// NOTE: Paused so that later code (which knows what the false branch will be) can end it correctly
@@ -164,7 +164,7 @@ void MIR_LowerHIR_Match( MirBuilder& builder, MirConverter& conv, ::HIR::ExprNod
else {
DEBUG("Arm result");
// - Set result
- builder.push_stmt_assign( result_val.clone(), builder.get_result(arm.m_code->span()) );
+ builder.push_stmt_assign( arm.m_code->span(), result_val.clone(), builder.get_result(arm.m_code->span()) );
// - Drop all non-moved values from this scope
builder.terminate_scope( arm.m_code->span(), mv$(drop_scope) );
// - Go to the next block
@@ -293,8 +293,8 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
(Value,
auto succ_bb = builder.new_bb_unlinked();
- auto test_lval = builder.lvalue_or_temp(te, ::MIR::Constant(re.as_Uint()));
- auto cmp_lval = builder.lvalue_or_temp(::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
+ auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint()));
+ auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
builder.set_cur_block(succ_bb);
),
@@ -315,8 +315,8 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
(Value,
auto succ_bb = builder.new_bb_unlinked();
- auto test_lval = builder.lvalue_or_temp(te, ::MIR::Constant(re.as_Int()));
- auto cmp_lval = builder.lvalue_or_temp(::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
+ auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Int()));
+ auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
builder.set_cur_block(succ_bb);
),
@@ -333,8 +333,8 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
(Value,
auto succ_bb = builder.new_bb_unlinked();
- auto test_lval = builder.lvalue_or_temp(te, ::MIR::Constant(re.as_Uint()));
- auto cmp_lval = builder.lvalue_or_temp(::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
+ auto test_lval = builder.lvalue_or_temp(sp, te, ::MIR::Constant(re.as_Uint()));
+ auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ match_val.clone(), ::MIR::eBinOp::EQ, mv$(test_lval) }));
builder.end_block( ::MIR::Terminator::make_If({ mv$(cmp_lval), succ_bb, fail_bb }) );
builder.set_cur_block(succ_bb);
),
@@ -2053,15 +2053,15 @@ void DecisionTreeGen::generate_tree_code(
auto next_bb = (&branch == &branches.back() ? default_bb : m_builder.new_bb_unlinked());
- auto test_val = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Str), ::MIR::Constant(branch.first) );
+ auto test_val = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Str), ::MIR::Constant(branch.first) );
auto cmp_gt_bb = m_builder.new_bb_unlinked();
- auto lt_val = m_builder.lvalue_or_temp( ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ have_val.clone(), ::MIR::eBinOp::LT, test_val.clone() }) );
+ auto lt_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ have_val.clone(), ::MIR::eBinOp::LT, test_val.clone() }) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(lt_val), default_bb, cmp_gt_bb }) );
m_builder.set_cur_block(cmp_gt_bb);
auto eq_bb = m_builder.new_bb_unlinked();
- auto gt_val = m_builder.lvalue_or_temp( ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(have_val), ::MIR::eBinOp::GT, test_val.clone() }) );
+ auto gt_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(have_val), ::MIR::eBinOp::GT, test_val.clone() }) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(gt_val), next_bb, eq_bb }) );
m_builder.set_cur_block(eq_bb);
@@ -2123,17 +2123,17 @@ void DecisionTreeGen::generate_branches_Unsigned(
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
- auto val_start = m_builder.lvalue_or_temp(ty, ::MIR::Constant(branch.first.start));
- auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(ty, ::MIR::Constant(branch.first.end)));
+ auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
+ auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
auto cmp_gt_block = m_builder.new_bb_unlinked();
- auto val_cmp_lt = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
+ auto val_cmp_lt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_lt), default_block, cmp_gt_block }) );
m_builder.set_cur_block( cmp_gt_block );
auto success_block = m_builder.new_bb_unlinked();
- auto val_cmp_gt = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
+ auto val_cmp_gt = m_builder.lvalue_or_temp(sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
@@ -2170,17 +2170,17 @@ void DecisionTreeGen::generate_branches_Char(
{
auto next_block = (&branch == &branches.back() ? default_block : m_builder.new_bb_unlinked());
- auto val_start = m_builder.lvalue_or_temp(ty, ::MIR::Constant(branch.first.start));
- auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(ty, ::MIR::Constant(branch.first.end)));
+ auto val_start = m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.start));
+ auto val_end = (branch.first.end == branch.first.start ? val_start.clone() : m_builder.lvalue_or_temp(sp, ty, ::MIR::Constant(branch.first.end)));
auto cmp_gt_block = m_builder.new_bb_unlinked();
- auto val_cmp_lt = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
+ auto val_cmp_lt = m_builder.lvalue_or_temp( sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::LT, mv$(val_start)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_lt), default_block, cmp_gt_block }) );
m_builder.set_cur_block( cmp_gt_block );
auto success_block = m_builder.new_bb_unlinked();
- auto val_cmp_gt = m_builder.lvalue_or_temp( ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
+ auto val_cmp_gt = m_builder.lvalue_or_temp( sp, ::HIR::TypeRef(::HIR::CoreType::Bool), ::MIR::RValue::make_BinOp({
val.clone(), ::MIR::eBinOp::GT, mv$(val_end)
}) );
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(val_cmp_gt), next_block, success_block }) );
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index db9d3134..a58cc54d 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -18,23 +18,26 @@ MirBuilder::MirBuilder(const StaticTraitResolve& resolve, ::MIR::Function& outpu
m_result_valid(false),
m_fcn_scope(*this, 0)
{
+ Span sp;
set_cur_block( new_bb_unlinked() );
- m_scopes.push_back( ScopeDef {} );
+ m_scopes.push_back( ScopeDef { sp } );
m_scope_stack.push_back( 0 );
- m_scopes.push_back( ScopeDef { false, ScopeType::make_Temporaries({}) } );
+ m_scopes.push_back( ScopeDef { sp, ScopeType::make_Temporaries({}) } );
m_scope_stack.push_back( 1 );
}
MirBuilder::~MirBuilder()
{
+ // TODO: Function span
+ Span sp;
if( has_result() )
{
- push_stmt_assign( ::MIR::LValue::make_Return({}), get_result(Span()) );
+ push_stmt_assign( sp, ::MIR::LValue::make_Return({}), get_result(Span()) );
}
if( block_active() )
{
- terminate_scope( Span(), ScopeHandle { *this, 1 } );
- terminate_scope( Span(), mv$(m_fcn_scope) );
+ terminate_scope( sp, ScopeHandle { *this, 1 } );
+ terminate_scope( sp, mv$(m_fcn_scope) );
end_block( ::MIR::Terminator::make_Return({}) );
}
}
@@ -85,14 +88,14 @@ void MirBuilder::define_variable(unsigned int idx)
tmp_scope.states.push_back( VarState::Uninit );
return ::MIR::LValue::make_Temporary({rv});
}
-::MIR::LValue MirBuilder::lvalue_or_temp(const ::HIR::TypeRef& ty, ::MIR::RValue val)
+::MIR::LValue MirBuilder::lvalue_or_temp(const Span& sp, const ::HIR::TypeRef& ty, ::MIR::RValue val)
{
TU_IFLET(::MIR::RValue, val, Use, e,
return mv$(e);
)
else {
auto temp = new_temporary(ty);
- push_stmt_assign( ::MIR::LValue(temp.as_Temporary()), mv$(val) );
+ push_stmt_assign( sp, ::MIR::LValue(temp.as_Temporary()), mv$(val) );
return temp;
}
}
@@ -107,7 +110,7 @@ void MirBuilder::define_variable(unsigned int idx)
return rv;
}
-::MIR::LValue MirBuilder::get_result_lvalue(const Span& sp)
+::MIR::LValue MirBuilder::get_result_unwrap_lvalue(const Span& sp)
{
auto rv = get_result(sp);
TU_IFLET(::MIR::RValue, rv, Use, e,
@@ -117,6 +120,18 @@ void MirBuilder::define_variable(unsigned int idx)
BUG(sp, "LValue expected, got RValue");
}
}
+::MIR::LValue MirBuilder::get_result_in_lvalue(const Span& sp, const ::HIR::TypeRef& ty)
+{
+ auto rv = get_result(sp);
+ TU_IFLET(::MIR::RValue, rv, Use, e,
+ return mv$(e);
+ )
+ else {
+ auto temp = new_temporary(ty);
+ push_stmt_assign( sp, ::MIR::LValue(temp.clone()), mv$(rv) );
+ return temp;
+ }
+}
void MirBuilder::set_result(const Span& sp, ::MIR::RValue val)
{
if(m_result_valid) {
@@ -126,9 +141,8 @@ void MirBuilder::set_result(const Span& sp, ::MIR::RValue val)
m_result_valid = true;
}
-void MirBuilder::push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val)
+void MirBuilder::push_stmt_assign(const Span& sp, ::MIR::LValue dst, ::MIR::RValue val)
{
- static Span sp;
ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
ASSERT_BUG(sp, dst.tag() != ::MIR::LValue::TAGDEAD, "");
ASSERT_BUG(sp, val.tag() != ::MIR::RValue::TAGDEAD, "");
@@ -234,7 +248,7 @@ void MirBuilder::push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val)
case VarState::Init:
// 1. Must be mut
// 2. Drop (if not Copy)
- push_stmt_drop( dst.clone() );
+ push_stmt_drop( sp, dst.clone() );
break;
case VarState::MaybeMoved:
// TODO: Conditional drop
@@ -245,10 +259,8 @@ void MirBuilder::push_stmt_assign(::MIR::LValue dst, ::MIR::RValue val)
)
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Assign({ mv$(dst), mv$(val) }) );
}
-void MirBuilder::push_stmt_drop(::MIR::LValue val)
+void MirBuilder::push_stmt_drop(const Span& sp, ::MIR::LValue val)
{
- static Span sp_drop;
- const auto& sp = sp_drop;
ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
ASSERT_BUG(sp, val.tag() != ::MIR::LValue::TAGDEAD, "");
@@ -309,7 +321,7 @@ void MirBuilder::end_block(::MIR::Terminator term)
ScopeHandle MirBuilder::new_scope_var(const Span& sp)
{
unsigned int idx = m_scopes.size();
- m_scopes.push_back( {false, ScopeType::make_Variables({})} );
+ m_scopes.push_back( ScopeDef {sp, ScopeType::make_Variables({})} );
m_scope_stack.push_back( idx );
DEBUG("START (var) scope " << idx);
return ScopeHandle { *this, idx };
@@ -317,7 +329,7 @@ ScopeHandle MirBuilder::new_scope_var(const Span& sp)
ScopeHandle MirBuilder::new_scope_temp(const Span& sp)
{
unsigned int idx = m_scopes.size();
- m_scopes.push_back( {false, ScopeType::make_Temporaries({})} );
+ m_scopes.push_back( ScopeDef {sp, ScopeType::make_Temporaries({})} );
m_scope_stack.push_back( idx );
DEBUG("START (temp) scope " << idx);
return ScopeHandle { *this, idx };
@@ -325,7 +337,7 @@ ScopeHandle MirBuilder::new_scope_temp(const Span& sp)
ScopeHandle MirBuilder::new_scope_split(const Span& sp)
{
unsigned int idx = m_scopes.size();
- m_scopes.push_back( {false, ScopeType::make_Split({})} );
+ m_scopes.push_back( ScopeDef {sp, ScopeType::make_Split({})} );
m_scopes.back().data.as_Split().arms.push_back( {} );
m_scope_stack.push_back( idx );
DEBUG("START (split) scope " << idx);
@@ -334,7 +346,7 @@ ScopeHandle MirBuilder::new_scope_split(const Span& sp)
ScopeHandle MirBuilder::new_scope_loop(const Span& sp)
{
unsigned int idx = m_scopes.size();
- m_scopes.push_back( {false, ScopeType::make_Loop({})} );
+ m_scopes.push_back( ScopeDef {sp, ScopeType::make_Loop({})} );
m_scope_stack.push_back( idx );
DEBUG("START (loop) scope " << idx);
return ScopeHandle { *this, idx };
@@ -831,7 +843,7 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd)
for(auto tmp_idx : ::reverse(e.temporaries))
{
if( get_temp_state(tmp_idx) == VarState::Init ) {
- push_stmt_drop( ::MIR::LValue::make_Temporary({ tmp_idx }) );
+ push_stmt_drop( sd.span, ::MIR::LValue::make_Temporary({ tmp_idx }) );
set_temp_state(tmp_idx, VarState::Dropped);
}
}
@@ -846,7 +858,7 @@ void MirBuilder::drop_scope_values(const ScopeDef& sd)
case VarState::Moved:
break;
case VarState::Init:
- push_stmt_drop( ::MIR::LValue::make_Variable(var_idx) );
+ push_stmt_drop( sd.span, ::MIR::LValue::make_Variable(var_idx) );
break;
case VarState::MaybeMoved:
//TODO(Span(), "MaybeMoved");