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.cpp400
1 files changed, 285 insertions, 115 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 5a629233..697f8141 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -18,6 +18,8 @@
#include "operations.hpp"
#include <mir/visit_crate_mir.hpp>
#include <hir/expr_state.hpp>
+#include <trans/target.hpp> // Target_GetSizeAndAlignOf - for `box`
+#include <cctype> // isdigit
namespace {
@@ -50,7 +52,7 @@ namespace {
struct LoopDesc {
ScopeHandle scope;
- ::std::string label;
+ RcString label;
unsigned int cur;
unsigned int next;
::MIR::LValue res_value;
@@ -161,6 +163,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
{
+ TRACE_FUNCTION_F(pat << ", allow_refutable=" << allow_refutable);
if( allow_refutable != 3 && pat.m_binding.is_valid() ) {
if( allow_refutable == 2 ) {
BUG(sp, "Binding when not expected");
@@ -173,6 +176,11 @@ namespace {
destructure_from_ex(sp, pat, lval.clone(), 3);
}
+ for(size_t i = 0; i < pat.m_binding.m_implicit_deref_count; i ++)
+ {
+ lval = ::MIR::LValue::new_Deref(mv$(lval));
+ }
+
switch( pat.m_binding.m_type )
{
case ::HIR::PatternBinding::Type::Move:
@@ -206,90 +214,117 @@ namespace {
allow_refutable = 2;
}
- TU_MATCHA( (pat.m_data), (e),
- (Any,
- ),
- (Box,
- destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable);
- ),
- (Ref,
- destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable);
- ),
- (Tuple,
+ for(size_t i = 0; i < pat.m_implicit_deref_count; i ++)
+ {
+ lval = ::MIR::LValue::new_Deref(mv$(lval));
+ }
+
+ TU_MATCH_HDRA( (pat.m_data), {)
+ TU_ARMA(Any, e) {
+ }
+ TU_ARMA(Box, e) {
+ destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable);
+ }
+ TU_ARMA(Ref, e) {
+ destructure_from_ex(sp, *e.sub, ::MIR::LValue::new_Deref(mv$(lval)), allow_refutable);
+ }
+ TU_ARMA(Tuple, e) {
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
- destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable);
+ destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable);
}
- ),
- (SplitTuple,
+ }
+ TU_ARMA(SplitTuple, e) {
assert(e.total_size >= e.leading.size() + e.trailing.size());
for(unsigned int i = 0; i < e.leading.size(); i ++ )
{
- destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable);
+ destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable);
}
// TODO: Is there a binding in the middle?
unsigned int ofs = e.total_size - e.trailing.size();
for(unsigned int i = 0; i < e.trailing.size(); i ++ )
{
- destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), ofs+i}), allow_refutable);
+ destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), ofs+i), allow_refutable);
}
- ),
- (StructValue,
+ }
+ TU_ARMA(StructValue, e) {
// Nothing.
- ),
- (StructTuple,
+ }
+ TU_ARMA(StructTuple, e) {
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
- destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable);
+ destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable);
}
- ),
- (Struct,
+ }
+ TU_ARMA(Struct, e) {
const auto& str = *e.binding;
- const auto& fields = str.m_data.as_Named();
- for(const auto& fld_pat : e.sub_patterns)
+ if( !e.sub_patterns.empty() )
{
- unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin();
- destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval.clone() ), idx}), allow_refutable);
+ ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct - " << pat);
+ const auto& fields = str.m_data.as_Named();
+ for(const auto& fld_pat : e.sub_patterns)
+ {
+ unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin();
+ destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable);
+ }
+ }
}
- ),
// Refutable
- (Value,
+ TU_ARMA(Value, e) {
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
- ),
- (Range,
+ }
+ TU_ARMA(Range, e) {
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
- ),
- (EnumValue,
+ }
+ TU_ARMA(EnumValue, e) {
const auto& enm = *e.binding_ptr;
if( enm.num_variants() > 1 )
{
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
}
- ),
- (EnumTuple,
+ }
+ TU_ARMA(EnumTuple, e) {
const auto& enm = *e.binding_ptr;
- ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
- auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx });
+ const auto& variants = enm.m_data.as_Data();
+ // TODO: Check that this is the only non-impossible arm
+ if( !allow_refutable )
+ {
+ for(size_t i = 0; i < variants.size(); i ++)
+ {
+ const auto& var_ty = variants[i].type;
+ if( i == e.binding_idx ) {
+ continue;
+ }
+ ::HIR::TypeRef tmp;
+ const auto& ty = (monomorphise_type_needed(var_ty) ? tmp = monomorphise_type_with(sp, var_ty, monomorphise_type_get_cb(sp, nullptr, &e.path.m_params, nullptr)) : var_ty);
+ if( m_builder.resolve().type_is_impossible(sp, ty) ) {
+ continue;
+ }
+ ERROR(sp, E0000, "Variant " << variants[i].name << " not handled");
+ }
+ }
+ auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx);
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
- destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable);
+ destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::new_Field(lval_var.clone(), i), allow_refutable);
}
- ),
- (EnumStruct,
+ }
+ TU_ARMA(EnumStruct, e) {
const auto& enm = *e.binding_ptr;
ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
ASSERT_BUG(sp, enm.m_data.is_Data(), "Expected struct variant - " << pat);
const auto& var = enm.m_data.as_Data()[e.binding_idx];;
const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct - " << e.path);
const auto& fields = str.m_data.as_Named();
- auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx });
+ auto lval_var = ::MIR::LValue::new_Downcast(mv$(lval), e.binding_idx);
for(const auto& fld_pat : e.sub_patterns)
{
unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin();
- destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval_var.clone() ), idx}), allow_refutable);
+ destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::new_Field(lval_var.clone(), idx), allow_refutable);
}
- ),
- (Slice,
+ }
+ TU_ARMA(Slice, e) {
// These are only refutable if T is [T]
bool ty_is_array = false;
m_builder.with_val_type(sp, lval, [&ty_is_array](const auto& ty){
@@ -301,7 +336,7 @@ namespace {
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++)
{
const auto& subpat = e.sub_patterns[i];
- destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable );
+ destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable );
}
}
else
@@ -312,11 +347,11 @@ namespace {
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++)
{
const auto& subpat = e.sub_patterns[i];
- destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable );
+ destructure_from_ex(sp, subpat, ::MIR::LValue::new_Field(lval.clone(), i), allow_refutable );
}
}
- ),
- (SplitSlice,
+ }
+ TU_ARMA(SplitSlice, e) {
// These are only refutable if T is [T]
bool ty_is_array = false;
unsigned int array_size = 0;
@@ -340,7 +375,7 @@ namespace {
for(unsigned int i = 0; i < e.leading.size(); i ++)
{
unsigned int idx = 0 + i;
- destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable );
+ destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable );
}
if( e.extra_bind.is_valid() )
{
@@ -349,7 +384,7 @@ namespace {
for(unsigned int i = 0; i < e.trailing.size(); i ++)
{
unsigned int idx = array_size - e.trailing.size() + i;
- destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable );
+ destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable );
}
}
else
@@ -375,13 +410,13 @@ namespace {
::MIR::LValue len_lval;
if( e.extra_bind.is_valid() || e.trailing.size() > 0 )
{
- len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval).clone() }));
+ len_lval = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, lval) }));
}
for(unsigned int i = 0; i < e.leading.size(); i ++)
{
unsigned int idx = i;
- destructure_from_ex(sp, e.leading[i], ::MIR::LValue::make_Field({ box$(lval.clone()), idx }), allow_refutable );
+ destructure_from_ex(sp, e.leading[i], ::MIR::LValue::new_Field(lval.clone(), idx), allow_refutable );
}
if( e.extra_bind.is_valid() )
{
@@ -392,9 +427,10 @@ namespace {
// 2. Obtain pointer to element
::HIR::BorrowType bt = H::get_borrow_type(sp, e.extra_bind);
::MIR::LValue ptr_val = m_builder.lvalue_or_temp(sp,
- ::HIR::TypeRef::new_pointer( bt, inner_type.clone() ),
- ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::make_Field({ box$(lval.clone()), static_cast<unsigned int>(e.leading.size()) }) })
+ ::HIR::TypeRef::new_borrow( bt, inner_type.clone() ),
+ ::MIR::RValue::make_Borrow({ 0, bt, ::MIR::LValue::new_Field( lval.clone(), static_cast<unsigned int>(e.leading.size()) ) })
);
+ // TODO: Cast to raw pointer? Or keep as a borrow?
// Construct fat pointer
m_builder.push_stmt_assign( sp, m_builder.get_variable(sp, e.extra_bind.m_slot), ::MIR::RValue::make_MakeDst({ mv$(ptr_val), mv$(len_val) }) );
@@ -407,15 +443,20 @@ namespace {
auto sub_val = ::MIR::Param(::MIR::Constant::make_Uint({ e.trailing.size() - i, ::HIR::CoreType::Usize }));
::MIR::LValue ofs_val = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_BinOp({ len_lval.clone(), ::MIR::eBinOp::SUB, mv$(sub_val) }) );
// Recurse with the indexed value
- destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Index({ box$(lval.clone()), box$(ofs_val) }), allow_refutable);
+ destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::new_Index( lval.clone(), ofs_val.m_root.as_Local() ), allow_refutable);
}
}
}
- )
- )
+ }
+ } // TU_MATCH_HDRA
}
// -- ExprVisitor
+ void visit_node_ptr(::HIR::ExprNodeP& node_p) override
+ {
+ DEBUG(node_p.get());
+ ::HIR::ExprVisitor::visit_node_ptr(node_p);
+ }
void visit(::HIR::ExprNode_Block& node) override
{
TRACE_FUNCTION_F("_Block");
@@ -521,7 +562,7 @@ namespace {
// Outputs can also (sometimes) be rvalues (only for `*m`?)
for(auto& v : node.m_outputs) {
this->visit_node_ptr(v.value);
- if( v.spec[0] != '=' )
+ if( v.spec[0] != '=' && v.spec[0] != '+' ) // TODO: what does '+' mean?
ERROR(node.span(), E0000, "Assembly output specifiers must start with =");
::MIR::LValue lv;
if(v.spec[1] == '*')
@@ -539,7 +580,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.push_stmt_assign( node.span(), ::MIR::LValue::new_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({}) );
}
@@ -643,6 +684,11 @@ namespace {
}
target_block = &*it;
}
+ else {
+ if( target_block->label != "" && target_block->label.c_str()[0] == '#' ) {
+ TODO(node.span(), "Break within try block, want to break parent loop instead");
+ }
+ }
if( node.m_continue ) {
ASSERT_BUG(node.span(), !node.m_value, "Continue with a value isn't valid");
@@ -1217,7 +1263,7 @@ namespace {
}
void visit(::HIR::ExprNode_Cast& node) override
{
- TRACE_FUNCTION_F("_Cast");
+ TRACE_FUNCTION_F("_Cast " << node.m_res_type);
this->visit_node_ptr(node.m_value);
const auto& ty_out = node.m_res_type;
@@ -1231,11 +1277,15 @@ namespace {
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),
- (
+ TU_MATCH_HDRA( (ty_out.m_data), {)
+ default:
BUG(node.span(), "Invalid cast to " << ty_out << " from " << ty_in);
- ),
- (Pointer,
+ TU_ARMA(Function, de) {
+ // Just trust the previous stages.
+ ASSERT_BUG(node.span(), ty_in.m_data.is_Function(), ty_in);
+ ASSERT_BUG(node.span(), de.m_arg_types == ty_in.m_data.as_Function().m_arg_types, ty_in);
+ }
+ TU_ARMA(Pointer, de) {
if( ty_in.m_data.is_Primitive() ) {
const auto& ie = ty_in.m_data.as_Primitive();
switch(ie)
@@ -1269,8 +1319,8 @@ namespace {
else {
BUG(node.span(), "Cannot cast to pointer from " << ty_in);
}
- ),
- (Primitive,
+ }
+ TU_ARMA(Primitive, de) {
switch(de)
{
case ::HIR::CoreType::Str:
@@ -1337,8 +1387,8 @@ namespace {
}
break;
}
- )
- )
+ }
+ }
auto res = m_builder.new_temporary(node.m_res_type);
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) );
@@ -1435,7 +1485,7 @@ namespace {
limit_val = ::MIR::Constant::make_Uint({ e.size_val, ::HIR::CoreType::Usize });
),
(Slice,
- limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value).clone() });
+ limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value) });
)
)
@@ -1469,7 +1519,13 @@ namespace {
m_builder.set_cur_block( arm_continue );
}
- m_builder.set_result( node.span(), ::MIR::LValue::make_Index({ box$(value), box$(index) }) );
+ if( !index.is_Local())
+ {
+ auto local_idx = m_builder.new_temporary(::HIR::CoreType::Usize);
+ m_builder.push_stmt_assign(node.span(), local_idx.clone(), mv$(index));
+ index = mv$(local_idx);
+ }
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Index( mv$(value), index.m_root.as_Local() ) );
}
void visit(::HIR::ExprNode_Deref& node) override
@@ -1481,8 +1537,8 @@ namespace {
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),
- (
+ TU_MATCH_HDRA( (ty_val.m_data), {)
+ default: {
if( m_builder.is_type_owned_box( ty_val ) )
{
// Box magically derefs.
@@ -1543,20 +1599,31 @@ namespace {
m_builder.set_cur_block(ok_block);
}
- ),
- (Pointer,
+ }
+ TU_ARMA(Pointer, te) {
// Deref on a pointer - TODO: Requires unsafe
- ),
- (Borrow,
+ }
+ TU_ARMA(Borrow, te) {
// Deref on a borrow - Always valid... assuming borrowck is there :)
- )
- )
+ }
+ }
- m_builder.set_result( node.span(), ::MIR::LValue::make_Deref({ box$(val) }) );
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Deref( mv$(val) ) );
}
void visit(::HIR::ExprNode_Emplace& node) override
{
+ switch(gTargetVersion)
+ {
+ case TargetVersion::Rustc1_19:
+ return visit_emplace_119(node);
+ case TargetVersion::Rustc1_29:
+ return visit_emplace_129(node);
+ }
+ throw "BUG: Unhandled target version";
+ }
+ void visit_emplace_119(::HIR::ExprNode_Emplace& node)
+ {
if( node.m_type == ::HIR::ExprNode_Emplace::Type::Noop ) {
return node.m_value->visit(*this);
}
@@ -1652,7 +1719,7 @@ namespace {
// 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) );
+ m_builder.push_stmt_assign( node.span(), ::MIR::LValue::new_Deref(place_raw.clone()), mv$(val), /*drop_destination=*/false );
// 3. Return a call to `finalize`
::HIR::Path finalize_path(::HIR::GenericPath {});
@@ -1689,6 +1756,92 @@ namespace {
m_builder.mark_value_assigned(node.span(), res);
m_builder.set_result( node.span(), mv$(res) );
}
+ void visit_emplace_129(::HIR::ExprNode_Emplace& node)
+ {
+ assert( node.m_type == ::HIR::ExprNode_Emplace::Type::Boxer );
+ const auto& data_ty = node.m_value->m_res_type;
+
+ node.m_value->visit(*this);
+ auto val = m_builder.get_result(node.span());
+
+ const auto& lang_exchange_malloc = m_builder.crate().get_lang_item_path(node.span(), "exchange_malloc");
+ const auto& lang_owned_box = m_builder.crate().get_lang_item_path(node.span(), "owned_box");
+
+ ::HIR::PathParams trait_params_data;
+ trait_params_data.m_types.push_back( data_ty.clone() );
+
+ // 1. Determine the size/alignment of the type
+ ::MIR::Param size_param, align_param;
+ size_t item_size, item_align;
+ if( Target_GetSizeAndAlignOf(node.span(), m_builder.resolve(), data_ty, item_size, item_align) ) {
+ size_param = ::MIR::Constant::make_Int({ static_cast<int64_t>(item_size), ::HIR::CoreType::Usize });
+ align_param = ::MIR::Constant::make_Int({ static_cast<int64_t>(item_align), ::HIR::CoreType::Usize });
+ }
+ else {
+ // Insert calls to "size_of" and "align_of" intrinsics
+ auto size_slot = m_builder.new_temporary( ::HIR::CoreType::Usize );
+ auto size__panic = m_builder.new_bb_unlinked();
+ auto size__ok = m_builder.new_bb_unlinked();
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ size__ok, size__panic,
+ size_slot.clone(), ::MIR::CallTarget::make_Intrinsic({ "size_of", trait_params_data.clone() }),
+ {}
+ }));
+ m_builder.set_cur_block(size__panic); m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); // HACK
+ m_builder.set_cur_block(size__ok);
+ auto align_slot = m_builder.new_temporary( ::HIR::CoreType::Usize );
+ auto align__panic = m_builder.new_bb_unlinked();
+ auto align__ok = m_builder.new_bb_unlinked();
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ align__ok, align__panic,
+ align_slot.clone(), ::MIR::CallTarget::make_Intrinsic({ "align_of", trait_params_data.clone() }),
+ {}
+ }));
+ m_builder.set_cur_block(align__panic); m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); // HACK
+ m_builder.set_cur_block(align__ok);
+
+ size_param = ::std::move(size_slot);
+ align_param = ::std::move(align_slot);
+ }
+
+ // 2. Call the allocator function and get a pointer
+ // - NOTE: "exchange_malloc" returns a `*mut u8`, need to cast that to the target type
+ auto place_raw_type = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Unique, ::HIR::CoreType::U8);
+ auto place_raw = m_builder.new_temporary( place_raw_type );
+
+ auto place__panic = m_builder.new_bb_unlinked();
+ auto place__ok = m_builder.new_bb_unlinked();
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ place__ok, place__panic,
+ place_raw.clone(), ::HIR::Path(lang_exchange_malloc),
+ make_vec2<::MIR::Param>( ::std::move(size_param), ::std::move(align_param) )
+ }));
+ m_builder.set_cur_block(place__panic); m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); // HACK
+ m_builder.set_cur_block(place__ok);
+
+ auto place_type = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Unique, data_ty.clone());
+ auto place = m_builder.new_temporary( place_type );
+ m_builder.push_stmt_assign(node.span(), place.clone(), ::MIR::RValue::make_Cast({ mv$(place_raw), place_type.clone() }));
+ // 3. Do a non-dropping write into the target location (i.e. just a MIR assignment)
+ m_builder.push_stmt_assign(node.span(), ::MIR::LValue::new_Deref(place.clone()), mv$(val), /*drop_destination=*/false);
+ // 4. Convert the pointer into an `owned_box`
+ auto res_type = ::HIR::TypeRef::new_path(::HIR::GenericPath(lang_owned_box, mv$(trait_params_data)), &m_builder.crate().get_struct_by_path(node.span(), lang_owned_box));
+ auto res = m_builder.new_temporary(res_type);
+ auto cast__panic = m_builder.new_bb_unlinked();
+ auto cast__ok = m_builder.new_bb_unlinked();
+ ::HIR::PathParams transmute_params;
+ transmute_params.m_types.push_back( res_type.clone() );
+ transmute_params.m_types.push_back( place_type.clone() );
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ cast__ok, cast__panic,
+ res.clone(), ::MIR::CallTarget::make_Intrinsic({ "transmute", mv$(transmute_params) }),
+ make_vec1( ::MIR::Param( mv$(place) ) )
+ }));
+ m_builder.set_cur_block(cast__panic); m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); // HACK
+ m_builder.set_cur_block(cast__ok);
+
+ m_builder.set_result(node.span(), mv$(res));
+ }
void visit(::HIR::ExprNode_TupleVariant& node) override
{
@@ -1810,6 +1963,14 @@ namespace {
mv$(values)
}));
}
+ if( fcn.m_abi == "platform-intrinsic" )
+ {
+ m_builder.end_block(::MIR::Terminator::make_Call({
+ next_block, panic_block,
+ res.clone(), ::MIR::CallTarget::make_Intrinsic({ RcString(FMT("platform:" << gpath.m_path.m_components.back())), gpath.m_params.clone() }),
+ mv$(values)
+ }));
+ }
// rustc has drop_in_place as a lang item, mrustc uses an intrinsic
if( gpath.m_path == m_builder.crate().get_lang_item_path_opt("drop_in_place") )
@@ -1901,29 +2062,29 @@ namespace {
}
void visit(::HIR::ExprNode_Field& node) override
{
- TRACE_FUNCTION_F("_Field");
+ TRACE_FUNCTION_F("_Field \"" << node.m_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;
- m_builder.set_result( node.span(), ::MIR::LValue::make_Field({ box$(val), idx }) );
+ if( ::std::isdigit(node.m_field.c_str()[0]) ) {
+ ::std::stringstream(node.m_field.c_str()) >> idx;
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) );
}
else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Struct() ) {
const auto& str = **bep;
const auto& fields = str.m_data.as_Named();
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_Field({ box$(val), idx }) );
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Field( mv$(val), idx ) );
}
else if( const auto* bep = val_ty.m_data.as_Path().binding.opt_Union() ) {
const auto& unm = **bep;
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 }) );
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Downcast( mv$(val), idx ) );
}
else {
BUG(node.span(), "Field access on non-union/struct - " << val_ty);
@@ -2041,7 +2202,7 @@ namespace {
// TODO: Ideally, the creation of the wrapper function would happen somewhere before trans?
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()) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) );
m_builder.set_result( sp, mv$(tmp) );
return ;
}
@@ -2052,11 +2213,11 @@ namespace {
),
(Constant,
auto tmp = m_builder.new_temporary( e.m_type );
- m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({node.m_path.clone()}) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_Const({box$(node.m_path.clone())}) );
m_builder.set_result( node.span(), mv$(tmp) );
),
(Static,
- m_builder.set_result( node.span(), ::MIR::LValue::make_Static(node.m_path.clone()) );
+ m_builder.set_result( node.span(), ::MIR::LValue::new_Static(node.m_path.clone()) );
),
(StructConstant,
// TODO: Why is this still a PathValue?
@@ -2101,13 +2262,13 @@ namespace {
fcn_ty_data.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
}
auto tmp = m_builder.new_temporary( ::HIR::TypeRef( mv$(fcn_ty_data) ) );
- m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) );
m_builder.set_result( sp, mv$(tmp) );
),
(StructConstructor,
// 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()) );
+ m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) );
m_builder.set_result( sp, mv$(tmp) );
)
)
@@ -2119,13 +2280,13 @@ namespace {
ASSERT_BUG(sp, it != tr.m_values.end(), "Cannot find trait item for " << node.m_path);
TU_MATCHA( (it->second), (e),
(Constant,
- m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) );
+ m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) );
),
(Static,
TODO(sp, "Associated statics (non-rustc) - " << node.m_path);
),
(Function,
- m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
+ m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) );
)
)
),
@@ -2141,7 +2302,7 @@ namespace {
{
auto it = impl.m_methods.find(pe.item);
if( it != impl.m_methods.end() ) {
- m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
+ m_builder.set_result( sp, ::MIR::Constant::make_ItemAddr(box$(node.m_path.clone())) );
return true;
}
}
@@ -2149,7 +2310,7 @@ namespace {
{
auto it = impl.m_constants.find(pe.item);
if( it != impl.m_constants.end() ) {
- m_builder.set_result( sp, ::MIR::Constant::make_Const({node.m_path.clone()}) );
+ m_builder.set_result( sp, ::MIR::Constant::make_Const({box$(node.m_path.clone())}) );
return true;
}
}
@@ -2175,7 +2336,7 @@ namespace {
ASSERT_BUG(sp, str.m_data.is_Named(), "");
const ::HIR::t_struct_fields& fields = str.m_data.as_Named();
- ::MIR::LValue base_val;
+ auto base_val = ::MIR::LValue::new_Return();
if( node.m_base_value )
{
DEBUG("_StructLiteral - base");
@@ -2216,7 +2377,7 @@ namespace {
if( !node.m_base_value) {
ERROR(node.span(), E0000, "Field '" << fields[i].first << "' not specified");
}
- values[i] = ::MIR::LValue::make_Field({ box$( base_val.clone() ), i });
+ values[i] = ::MIR::LValue::new_Field( base_val.clone(), i );
}
else {
// Partial move support will handle dropping the rest?
@@ -2233,13 +2394,18 @@ namespace {
{
TRACE_FUNCTION_F("_StructLiteral");
- TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e),
- (Unbound, ),
- (Opaque, ),
- (Enum,
- auto enum_path = node.m_path.clone();
+ ASSERT_BUG(node.span(), node.m_path.m_data.is_Generic(), "_StructLiteral with non-Generic path - " << node.m_path);
+ const auto& ty_path = node.m_path.m_data.as_Generic();
+
+ TU_MATCH_HDRA( (node.m_res_type.m_data.as_Path().binding), {)
+ TU_ARMA(Unbound, _e) {
+ }
+ TU_ARMA(Opaque, _e) {
+ }
+ TU_ARMA(Enum, e) {
+ auto enum_path = ty_path.clone();
enum_path.m_path.m_components.pop_back();
- const auto& var_name = node.m_path.m_path.m_components.back();
+ const auto& var_name = ty_path.m_path.m_components.back();
const auto& enm = *e;
size_t idx = enm.find_variant(var_name);
@@ -2249,7 +2415,7 @@ namespace {
const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
// Take advantage of the identical generics to cheaply clone/monomorph the path.
- ::HIR::GenericPath struct_path = node.m_path.clone();
+ ::HIR::GenericPath struct_path = ty_path.clone();
struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path;
this->visit_sl_inner(node, str, struct_path);
@@ -2264,22 +2430,25 @@ namespace {
static_cast<unsigned>(idx),
mv$(v)
}) );
- ),
- (Union,
+ }
+ TU_ARMA(Union, e) {
BUG(node.span(), "_StructLiteral Union isn't valid?");
- ),
- (Struct,
+ }
+ TU_ARMA(ExternType, e) {
+ BUG(node.span(), "_StructLiteral ExternType isn't valid?");
+ }
+ TU_ARMA(Struct, e) {
if(e->m_data.is_Unit()) {
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
- node.m_path.clone(),
+ ty_path.clone(),
{}
}) );
return ;
}
- this->visit_sl_inner(node, *e, node.m_path);
- )
- )
+ this->visit_sl_inner(node, *e, ty_path);
+ }
+ }
}
void visit(::HIR::ExprNode_UnionLiteral& node) override
{
@@ -2391,7 +2560,7 @@ namespace {
else
{
ev.define_vars_from(ptr->span(), arg.first);
- ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::make_Argument({i}));
+ ev.destructure_from(ptr->span(), arg.first, ::MIR::LValue::new_Argument(i));
}
i ++;
}
@@ -2402,8 +2571,9 @@ namespace {
}
// NOTE: Can't clean up yet, as consteval isn't done
- //MIR_Cleanup(resolve, path, fcn, args, ptr->m_res_type);
- MIR_Validate(resolve, path, fcn, args, ptr->m_res_type);
+ //MIR_Cleanup(resolve, path, fcn, args, ret_ty);
+ //DEBUG("MIR Dump:" << ::std::endl << FMT_CB(ss, MIR_Dump_Fcn(ss, fcn, 1);));
+ MIR_Validate(resolve, path, fcn, args, ret_ty);
if( getenv("MRUSTC_VALIDATE_FULL_EARLY") ) {
MIR_Validate_Full(resolve, path, fcn, args, ptr->m_res_type);