summaryrefslogtreecommitdiff
path: root/src/mir/from_hir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mir/from_hir.cpp')
-rw-r--r--src/mir/from_hir.cpp312
1 files changed, 156 insertions, 156 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index c50806f5..48c0d948 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -20,14 +20,14 @@
namespace {
-
+
class ExprVisitor_Conv:
public MirConverter
{
MirBuilder& m_builder;
-
+
const ::std::vector< ::HIR::TypeRef>& m_variable_types;
-
+
struct LoopDesc {
ScopeHandle scope;
::std::string label;
@@ -35,26 +35,26 @@ namespace {
unsigned int next;
};
::std::vector<LoopDesc> m_loop_stack;
-
+
public:
ExprVisitor_Conv(MirBuilder& builder, const ::std::vector< ::HIR::TypeRef>& var_types):
m_builder(builder),
m_variable_types(var_types)
{
}
-
+
void destructure_from(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, bool allow_refutable=false) override
{
destructure_from_ex(sp, pat, mv$(lval), (allow_refutable ? 1 : 0));
}
-
+
// Brings variables defined in `pat` into scope
void define_vars_from(const Span& sp, const ::HIR::Pattern& pat) override
{
if( pat.m_binding.is_valid() ) {
m_builder.define_variable( pat.m_binding.m_slot );
}
-
+
TU_MATCHA( (pat.m_data), (e),
(Any,
),
@@ -98,7 +98,7 @@ namespace {
),
(EnumValue,
),
-
+
(EnumTuple,
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
@@ -132,7 +132,7 @@ namespace {
)
)
}
-
+
void destructure_from_ex(const Span& sp, const ::HIR::Pattern& pat, ::MIR::LValue lval, int allow_refutable=0) // 1 : yes, 2 : disallow binding
{
if( allow_refutable != 3 && pat.m_binding.is_valid() ) {
@@ -146,7 +146,7 @@ namespace {
// Refutable and binding allowed
destructure_from_ex(sp, pat, lval.clone(), 3);
}
-
+
switch( pat.m_binding.m_type )
{
case ::HIR::PatternBinding::Type::Move:
@@ -168,7 +168,7 @@ namespace {
if( allow_refutable == 3 ) {
allow_refutable = 2;
}
-
+
TU_MATCHA( (pat.m_data), (e),
(Any,
),
@@ -267,7 +267,7 @@ namespace {
else
{
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
-
+
// TODO: Emit code to triple-check the size? Or just assume that match did that correctly.
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++)
{
@@ -320,7 +320,7 @@ namespace {
)
)
}
-
+
// -- ExprVisitor
void visit(::HIR::ExprNode_Block& node) override
{
@@ -329,38 +329,38 @@ namespace {
if( node.m_nodes.size() > 0 )
{
bool diverged = false;
-
+
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 ++)
{
auto& subnode = node.m_nodes[i];
const Span& sp = subnode->span();
-
+
auto stmt_scope = m_builder.new_scope_temp(sp);
this->visit_node_ptr(subnode);
if( m_builder.has_result() ) {
// TODO: Drop.
m_builder.get_result(sp);
}
-
+
if( m_builder.block_active() ) {
m_builder.terminate_scope(sp, mv$(stmt_scope));
}
else {
auto _ = mv$(stmt_scope);
-
+
m_builder.set_cur_block( m_builder.new_bb_unlinked() );
diverged = true;
}
}
-
+
// For the last node, specially handle.
if( node.m_yields_final )
{
auto& subnode = node.m_nodes.back();
const Span& sp = subnode->span();
-
+
auto stmt_scope = m_builder.new_scope_temp(sp);
this->visit_node_ptr(subnode);
if( m_builder.has_result() || m_builder.block_active() )
@@ -368,10 +368,10 @@ namespace {
ASSERT_BUG(sp, m_builder.block_active(), "Result yielded, but no active block");
ASSERT_BUG(sp, m_builder.has_result(), "Active block but no result yeilded");
// PROBLEM: This can drop the result before we want to use it.
-
+
auto res = m_builder.get_result(sp);
m_builder.raise_variables(sp, res);
-
+
m_builder.terminate_scope(sp, mv$(stmt_scope));
m_builder.terminate_scope( node.span(), mv$(scope) );
m_builder.set_result( node.span(), mv$(res) );
@@ -407,7 +407,7 @@ namespace {
{
TRACE_FUNCTION_F("_Return");
this->visit_node_ptr(node.m_value);
-
+
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({}) );
@@ -419,11 +419,11 @@ namespace {
if( node.m_value )
{
this->visit_node_ptr(node.m_value);
-
+
if( ! m_builder.block_active() ) {
return ;
}
-
+
if( node.m_pattern.m_binding.is_valid() && node.m_pattern.m_data.is_Any() && node.m_pattern.m_binding.m_type == ::HIR::PatternBinding::Type::Move )
{
m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Variable(node.m_pattern.m_binding.m_slot), m_builder.get_result(node.span()) );
@@ -441,12 +441,12 @@ namespace {
auto loop_body_scope = m_builder.new_scope_loop(node.span());
auto loop_block = m_builder.new_bb_linked();
auto loop_next = m_builder.new_bb_unlinked();
-
+
m_loop_stack.push_back( LoopDesc { mv$(loop_body_scope), node.m_label, loop_block, loop_next } );
this->visit_node_ptr(node.m_code);
auto loop_scope = mv$(m_loop_stack.back().scope);
m_loop_stack.pop_back();
-
+
// If there's a stray result, drop it
if( m_builder.has_result() ) {
assert( m_builder.block_active() );
@@ -467,7 +467,7 @@ namespace {
// Terminate scope without emitting cleanup (cleanup was handled by `break`)
m_builder.terminate_scope( node.span(), mv$(loop_scope), false );
}
-
+
if( ! node.m_diverges )
{
DEBUG("- Doesn't diverge");
@@ -478,7 +478,7 @@ namespace {
{
DEBUG("- Diverges");
assert( !m_builder.has_result() );
-
+
m_builder.set_cur_block(loop_next);
m_builder.end_split_arm_early(node.span());
assert( !m_builder.has_result() );
@@ -491,7 +491,7 @@ namespace {
if( m_loop_stack.size() == 0 ) {
BUG(node.span(), "Loop control outside of a loop");
}
-
+
const auto* target_block = &m_loop_stack.back();
if( node.m_label != "" ) {
auto it = ::std::find_if(m_loop_stack.rbegin(), m_loop_stack.rend(), [&](const auto& x){ return x.label == node.m_label; });
@@ -500,7 +500,7 @@ namespace {
}
target_block = &*it;
}
-
+
// TODO: Insert drop of all active scopes within the loop
m_builder.terminate_scope_early( node.span(), target_block->scope );
if( node.m_continue ) {
@@ -510,13 +510,13 @@ namespace {
m_builder.end_block( ::MIR::Terminator::make_Goto(target_block->next) );
}
}
-
+
void visit(::HIR::ExprNode_Match& node) override
{
TRACE_FUNCTION_FR("_Match", "_Match");
this->visit_node_ptr(node.m_value);
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
//const auto& ty = node.m_value->m_res_type;
@@ -531,21 +531,21 @@ namespace {
// - Shortcut: Single-arm match
auto& arm = node.m_arms[0];
const auto& pat = arm.m_patterns[0];
-
+
auto scope = m_builder.new_scope_var(arm.m_code->span());
auto tmp_scope = m_builder.new_scope_temp(arm.m_code->span());
this->define_vars_from(node.span(), pat);
// TODO: Do the same shortcut as _Let?
this->destructure_from(node.span(), pat, mv$(match_val));
-
+
// Temp scope.
this->visit_node_ptr(arm.m_code);
-
+
if( m_builder.block_active() ) {
auto res = m_builder.get_result(arm.m_code->span());
m_builder.raise_variables( arm.m_code->span(), res );
m_builder.set_result(arm.m_code->span(), mv$(res));
-
+
m_builder.terminate_scope( node.span(), mv$(tmp_scope) );
m_builder.terminate_scope( node.span(), mv$(scope) );
}
@@ -558,11 +558,11 @@ namespace {
MIR_LowerHIR_Match(m_builder, *this, node, mv$(match_val));
}
} // ExprNode_Match
-
+
void visit(::HIR::ExprNode_If& node) override
{
TRACE_FUNCTION_FR("_If", "_If");
-
+
bool reverse = false;
{
auto* cond_p = &node.m_cond;
@@ -572,11 +572,11 @@ namespace {
cond_p = &cond_uni->m_value;
reverse = !reverse;
}
-
+
this->visit_node_ptr(*cond_p);
}
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();
auto next_block = m_builder.new_bb_unlinked();
@@ -586,12 +586,12 @@ namespace {
else {
m_builder.end_block( ::MIR::Terminator::make_If({ mv$(decision_val), true_branch, false_branch }) );
}
-
+
auto result_val = m_builder.new_temporary(node.m_res_type);
-
+
// Scope handles cases where one arm moves a value but the other doesn't
auto scope = m_builder.new_scope_split( node.m_true->span() );
-
+
// 'true' branch
{
auto stmt_scope = m_builder.new_scope_temp(node.m_true->span());
@@ -608,7 +608,7 @@ namespace {
m_builder.end_split_arm(node.span(), scope, false);
}
}
-
+
// 'false' branch
m_builder.set_cur_block(false_branch);
if( node.m_false )
@@ -636,10 +636,10 @@ namespace {
}
m_builder.set_cur_block(next_block);
m_builder.terminate_scope( node.span(), mv$(scope) );
-
+
m_builder.set_result( node.span(), mv$(result_val) );
}
-
+
void generate_checked_binop(const Span& sp, ::MIR::LValue res_slot, ::MIR::eBinOp op, ::MIR::LValue val_l, const ::HIR::TypeRef& ty_l, ::MIR::LValue val_r, const ::HIR::TypeRef& ty_r)
{
switch(op)
@@ -732,29 +732,29 @@ namespace {
break;
}
}
-
+
void visit(::HIR::ExprNode_Assign& node) override
{
TRACE_FUNCTION_F("_Assign");
const auto& sp = node.span();
-
+
this->visit_node_ptr(node.m_value);
::MIR::RValue val = m_builder.get_result(sp);
-
+
this->visit_node_ptr(node.m_slot);
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;
-
+
if( node.m_op != ::HIR::ExprNode_Assign::Op::None )
{
auto dst_clone = dst.clone();
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);
-
+
#define _(v) ::HIR::ExprNode_Assign::Op::v
::MIR::eBinOp op;
switch(node.m_op)
@@ -789,20 +789,20 @@ namespace {
}
m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
-
+
void visit(::HIR::ExprNode_BinOp& node) override
{
const auto& sp = node.span();
TRACE_FUNCTION_F("_BinOp");
-
+
const auto& ty_l = node.m_left->m_res_type;
this->visit_node_ptr(node.m_left);
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.get_result_in_lvalue(node.m_right->span(), ty_r);
-
+
auto res = m_builder.new_temporary(node.m_res_type);
::MIR::eBinOp op;
switch(node.m_op)
@@ -815,18 +815,18 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::CmpGtE: op = ::MIR::eBinOp::GE;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Xor: op = ::MIR::eBinOp::BIT_XOR; if(0)
case ::HIR::ExprNode_BinOp::Op::Or : op = ::MIR::eBinOp::BIT_OR ; if(0)
case ::HIR::ExprNode_BinOp::Op::And: op = ::MIR::eBinOp::BIT_AND;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Shr: op = ::MIR::eBinOp::BIT_SHR; if(0)
case ::HIR::ExprNode_BinOp::Op::Shl: op = ::MIR::eBinOp::BIT_SHL;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::Add: op = ::MIR::eBinOp::ADD; if(0)
case ::HIR::ExprNode_BinOp::Op::Sub: op = ::MIR::eBinOp::SUB; if(0)
case ::HIR::ExprNode_BinOp::Op::Mul: op = ::MIR::eBinOp::MUL; if(0)
@@ -834,7 +834,7 @@ namespace {
case ::HIR::ExprNode_BinOp::Op::Mod: op = ::MIR::eBinOp::MOD;
this->generate_checked_binop(sp, res.clone(), op, mv$(left), ty_l, mv$(right), ty_r);
break;
-
+
case ::HIR::ExprNode_BinOp::Op::BoolAnd: {
auto bb_next = m_builder.new_bb_unlinked();
auto bb_true = m_builder.new_bb_unlinked();
@@ -844,12 +844,12 @@ namespace {
m_builder.set_cur_block( bb_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(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 );
} break;
case ::HIR::ExprNode_BinOp::Op::BoolOr: {
@@ -861,26 +861,26 @@ namespace {
m_builder.set_cur_block( bb_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(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 );
} break;
}
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_UniOp& node) override
{
TRACE_FUNCTION_F("_UniOp");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), ty_val);
-
+
::MIR::RValue res;
switch(node.m_op)
{
@@ -934,11 +934,11 @@ namespace {
void visit(::HIR::ExprNode_Borrow& node) override
{
TRACE_FUNCTION_F("_Borrow");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
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( node.span(), res.as_Temporary(), ::MIR::RValue::make_Borrow({ 0, node.m_type, mv$(val) }));
m_builder.set_result( node.span(), mv$(res) );
@@ -947,16 +947,16 @@ namespace {
{
TRACE_FUNCTION_F("_Cast");
this->visit_node_ptr(node.m_value);
-
+
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
-
+
if( ty_out == ty_in ) {
return ;
}
-
+
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_out.m_data), (de),
(
BUG(node.span(), "Invalid cast to " << ty_out << " from " << ty_in);
@@ -1073,16 +1073,16 @@ namespace {
{
TRACE_FUNCTION_F("_Unsize");
this->visit_node_ptr(node.m_value);
-
+
const auto& ty_out = node.m_res_type;
const auto& ty_in = node.m_value->m_res_type;
-
+
if( ty_out == ty_in ) {
return ;
}
-
+
auto ptr_lval = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
if( ty_out.m_data.is_Borrow() && ty_in.m_data.is_Borrow() )
{
const auto& oe = ty_out.m_data.as_Borrow();
@@ -1141,14 +1141,14 @@ namespace {
vtable_params.m_types[idx] = ty_b.second.clone();
}
auto vtable_type = ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref );
-
+
::HIR::Path vtable { ty_in.clone(), e.m_trait.m_path.clone(), "#vtable" };
auto vtable_lval = m_builder.lvalue_or_temp(
node.span(),
::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, mv$(vtable_type)),
::MIR::RValue( ::MIR::Constant::make_ItemAddr(mv$(vtable)) )
);
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(vtable_lval) }) );
#else
m_builder.set_result( node.span(), ::MIR::RValue::make_Cast({ mv$(ptr_lval), node.m_res_type.clone() }) );
@@ -1170,16 +1170,16 @@ namespace {
void visit(::HIR::ExprNode_Index& node) override
{
TRACE_FUNCTION_F("_Index");
-
+
// 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.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.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),
(
@@ -1192,7 +1192,7 @@ namespace {
limit_val = ::MIR::RValue::make_DstMeta({ value.clone() });
)
)
-
+
TU_MATCH_DEF(::HIR::TypeRef::Data, (ty_idx.m_data), (e),
(
BUG(node.span(), "Indexing using unsupported index type " << ty_idx);
@@ -1203,38 +1203,38 @@ namespace {
}
)
)
-
+
// Range checking (DISABLED)
if( false )
{
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(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 }) );
-
+
m_builder.set_cur_block( arm_panic );
// TODO: Call an "index fail" method which always panics.
//m_builder.end_block( ::MIR::Terminator::make_Panic({}) );
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( arm_continue );
}
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(value), box$(index) }) );
}
-
+
void visit(::HIR::ExprNode_Deref& node) override
{
const Span& sp = node.span();
TRACE_FUNCTION_F("_Deref");
-
+
const auto& ty_val = node.m_value->m_res_type;
this->visit_node_ptr(node.m_value);
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),
(
if( m_builder.is_type_owned_box( ty_val ) )
@@ -1252,10 +1252,10 @@ namespace {
// Deref on a borrow - Always valid... assuming borrowck is there :)
)
)
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) );
}
-
+
void visit(::HIR::ExprNode_Emplace& node) override
{
if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) {
@@ -1266,9 +1266,9 @@ namespace {
auto path_Place = ::HIR::SimplePath("core", {"ops", "Place"});
auto path_Boxed = ::HIR::SimplePath("core", {"ops", "Boxed"});
//auto path_InPlace = ::HIR::SimplePath("core", {"ops", "InPlace"});
-
+
const auto& data_ty = node.m_value->m_res_type;
-
+
// 1. Obtain the type of the `place` variable
::HIR::TypeRef place_type;
switch( node.m_type )
@@ -1283,7 +1283,7 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
// 2. Initialise the place
auto place = m_builder.new_temporary( place_type );
auto place__panic = m_builder.new_bb_unlinked();
@@ -1305,13 +1305,13 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(place__panic);
// TODO: Drop `place`
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(place__ok);
-
+
// 2. Get `place_raw`
auto place_raw__type = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone());
auto place_raw = m_builder.new_temporary( place_raw__type );
@@ -1328,19 +1328,19 @@ namespace {
::make_vec1( mv$(place_refmut) )
}));
}
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(place_raw__panic);
// TODO: Drop `place`
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(place_raw__ok);
-
-
+
+
// 3. Get the value and assign it into `place_raw`
node.m_value->visit(*this);
auto val = m_builder.get_result(node.span());
m_builder.push_stmt_assign( node.span(), ::MIR::LValue::make_Deref({ box$(place_raw.clone()) }), mv$(val) );
-
+
// 3. Return a call to `finalize`
::HIR::Path finalize_path(::HIR::GenericPath {});
switch( node.m_type )
@@ -1354,7 +1354,7 @@ namespace {
TODO(node.span(), "_Emplace - Placer");
break;
}
-
+
auto res = m_builder.new_temporary( node.m_res_type );
auto res__panic = m_builder.new_bb_unlinked();
auto res__ok = m_builder.new_bb_unlinked();
@@ -1363,17 +1363,17 @@ namespace {
res.clone(), mv$(finalize_path),
::make_vec1( mv$(place) )
}));
-
+
// TODO: Proper panic handling, including scope destruction
m_builder.set_cur_block(res__panic);
// TODO: Should this drop the value written to the rawptr?
// - No, becuase it's likely invalid now. Goodbye!
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
m_builder.set_cur_block(res__ok);
-
+
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_TupleVariant& node) override
{
const Span& sp = node.span();
@@ -1385,7 +1385,7 @@ namespace {
this->visit_node_ptr(arg);
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
}
-
+
unsigned int variant_index = ~0u;
if( !node.m_is_struct )
{
@@ -1396,17 +1396,17 @@ namespace {
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
-
+
variant_index = var_it - enm.m_variants.begin();
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_path.clone(),
variant_index,
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_CallPath& node) override
{
TRACE_FUNCTION_F("_CallPath " << node.m_path);
@@ -1418,14 +1418,14 @@ namespace {
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
-
-
+
+
auto panic_block = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
auto res = m_builder.new_temporary( node.m_res_type );
-
+
bool unconditional_diverge = false;
-
+
// Emit intrinsics as a special call type
if( node.m_path.m_data.is_Generic() )
{
@@ -1439,13 +1439,13 @@ namespace {
mv$(values)
}));
}
-
+
if( fcn.m_return.m_data.is_Diverge() )
{
unconditional_diverge = true;
}
}
-
+
// If the call wasn't to an intrinsic, emit it as a path
if( m_builder.block_active() )
{
@@ -1455,11 +1455,11 @@ namespace {
mv$(values)
}));
}
-
+
m_builder.set_cur_block(panic_block);
// TODO: Proper panic handling, including scope destruction
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( next_block );
// If the function doesn't return, early-terminate the return block.
@@ -1475,16 +1475,16 @@ namespace {
}
m_builder.set_result( node.span(), mv$(res) );
}
-
+
void visit(::HIR::ExprNode_CallValue& node) override
{
TRACE_FUNCTION_F("_CallValue " << node.m_value->m_res_type);
-
+
// _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.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)
@@ -1493,8 +1493,8 @@ namespace {
values.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
m_builder.moved_lvalue( arg->span(), values.back() );
}
-
-
+
+
auto panic_block = m_builder.new_bb_unlinked();
auto next_block = m_builder.new_bb_unlinked();
auto res = m_builder.new_temporary( node.m_res_type );
@@ -1503,11 +1503,11 @@ namespace {
res.clone(), mv$(fcn_val),
mv$(values)
}));
-
+
m_builder.set_cur_block(panic_block);
// TODO: Proper panic handling
m_builder.end_block( ::MIR::Terminator::make_Diverge({}) );
-
+
m_builder.set_cur_block( next_block );
m_builder.set_result( node.span(), mv$(res) );
}
@@ -1521,9 +1521,9 @@ namespace {
TRACE_FUNCTION_F("_Field");
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
const auto& val_ty = node.m_value->m_res_type;
-
+
unsigned int idx;
if( '0' <= node.m_field[0] && node.m_field[0] <= '9' ) {
::std::stringstream(node.m_field) >> idx;
@@ -1539,7 +1539,7 @@ namespace {
const auto& unm = *node.m_value->m_res_type.m_data.as_Path().binding.as_Union();
const auto& fields = unm.m_variants;
idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto& x){ return x.first == node.m_field; } ) - fields.begin();
-
+
m_builder.set_result( node.span(), ::MIR::LValue::make_Downcast({ box$(val), idx }) );
}
}
@@ -1601,7 +1601,7 @@ namespace {
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
-
+
variant_index = var_it - enm.m_variants.begin();
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
@@ -1620,13 +1620,13 @@ namespace {
auto enum_path = pe.m_path;
enum_path.m_components.pop_back();
const auto& var_name = pe.m_path.m_components.back();
-
+
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << pe.m_path << " isn't present");
const auto& var = var_it->second;
ASSERT_BUG(sp, var.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple variant");
-
+
// TODO: Ideally, the creation of the wrapper function would happen somewhere before this?
auto tmp = m_builder.new_temporary( node.m_res_type );
m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
@@ -1676,7 +1676,7 @@ namespace {
BUG(sp, "Unknown param in free function - " << gt);
}
};
-
+
// TODO: Obtain function type for this function (i.e. a type that is specifically for this function)
auto fcn_ty_data = ::HIR::FunctionType {
e.m_unsafe,
@@ -1758,7 +1758,7 @@ namespace {
TRACE_FUNCTION_F("_Variable - " << node.m_name << " #" << node.m_slot);
m_builder.set_result( node.span(), ::MIR::LValue::make_Variable(node.m_slot) );
}
-
+
void visit(::HIR::ExprNode_StructLiteral& node) override
{
TRACE_FUNCTION_F("_StructLiteral");
@@ -1768,7 +1768,7 @@ namespace {
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);
}
-
+
unsigned int variant_index = ~0u;
const ::HIR::t_struct_fields* fields_ptr = nullptr;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e),
@@ -1791,12 +1791,12 @@ namespace {
)
assert(fields_ptr);
const ::HIR::t_struct_fields& fields = *fields_ptr;
-
+
::std::vector<bool> values_set;
::std::vector< ::MIR::LValue> values;
values.resize( fields.size() );
values_set.resize( fields.size() );
-
+
for(auto& ent : node.m_values)
{
auto& valnode = ent.second;
@@ -1804,7 +1804,7 @@ namespace {
assert( !values_set[idx] );
values_set[idx] = true;
this->visit_node_ptr(valnode);
-
+
// NOTE: Have to allocate a new temporary because ordering matters
auto tmp = m_builder.new_temporary(valnode->m_res_type);
m_builder.push_stmt_assign( valnode->span(), tmp.clone(), m_builder.get_result(valnode->span()) );
@@ -1822,7 +1822,7 @@ namespace {
// Partial move support will handle dropping the rest?
}
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_path.clone(),
variant_index,
@@ -1832,10 +1832,10 @@ namespace {
void visit(::HIR::ExprNode_UnionLiteral& node) override
{
TRACE_FUNCTION_F("_UnionLiteral " << node.m_path);
-
+
this->visit_node_ptr(node.m_value);
auto val = m_builder.get_result_in_lvalue(node.m_value->span(), node.m_value->m_res_type);
-
+
const auto& unm = *node.m_res_type.m_data.as_Path().binding.as_Union();
auto it = ::std::find_if(unm.m_variants.begin(), unm.m_variants.end(), [&](const auto&v)->auto{ return v.first == node.m_variant_name; });
assert(it != unm.m_variants.end());
@@ -1847,7 +1847,7 @@ namespace {
mv$(val)
}) );
}
-
+
void visit(::HIR::ExprNode_Tuple& node) override
{
TRACE_FUNCTION_F("_Tuple");
@@ -1858,12 +1858,12 @@ namespace {
this->visit_node_ptr(arg);
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({
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_ArrayList& node) override
{
TRACE_FUNCTION_F("_ArrayList");
@@ -1874,28 +1874,28 @@ namespace {
this->visit_node_ptr(arg);
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({
mv$(values)
}) );
}
-
+
void visit(::HIR::ExprNode_ArraySized& node) override
{
TRACE_FUNCTION_F("_ArraySized");
this->visit_node_ptr( node.m_val );
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),
static_cast<unsigned int>(node.m_size_val)
}) );
}
-
+
void visit(::HIR::ExprNode_Closure& node) override
{
TRACE_FUNCTION_F("_Closure - " << node.m_obj_path);
-
+
::std::vector< ::MIR::LValue> vals;
vals.reserve( node.m_captures.size() );
for(auto& arg : node.m_captures)
@@ -1903,7 +1903,7 @@ namespace {
this->visit_node_ptr(arg);
vals.push_back( m_builder.get_result_in_lvalue(arg->span(), arg->m_res_type) );
}
-
+
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_obj_path.clone(),
~0u,
@@ -1917,17 +1917,17 @@ namespace {
::MIR::FunctionPointer LowerMIR(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::HIR::ExprPtr& ptr, const ::HIR::Function::args_t& args)
{
TRACE_FUNCTION;
-
+
::MIR::Function fcn;
fcn.named_variables.reserve(ptr.m_bindings.size());
for(const auto& t : ptr.m_bindings)
fcn.named_variables.push_back( t.clone() );
-
+
// Scope ensures that builder cleanup happens before `fcn` is moved
{
MirBuilder builder { ptr->span(), resolve, args, fcn };
ExprVisitor_Conv ev { builder, ptr.m_bindings };
-
+
// 1. Apply destructuring to arguments
unsigned int i = 0;
for( const auto& arg : args )
@@ -1936,12 +1936,12 @@ namespace {
ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::make_Argument({i}));
i ++;
}
-
+
// 2. Destructure code
::HIR::ExprNode& root_node = const_cast<::HIR::ExprNode&>(*ptr);
root_node.visit( ev );
}
-
+
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}