summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mir/cleanup.cpp40
-rw-r--r--src/trans/codegen_c.cpp30
2 files changed, 24 insertions, 46 deletions
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index f790c78a..3dc7f418 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -959,45 +959,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
)
)
- if( se.src.is_Borrow() && se.src.as_Borrow().val.is_Field() )
- {
- auto& e = se.src.as_Borrow();
- // TODO: If borrowing a !Sized value via a field access, create the DST
- ::HIR::TypeRef tmp;
- const auto& src_ty = state.get_lvalue_type(tmp, e.val);
-
- if( !resolve.type_is_sized(sp, src_ty) && !src_ty.m_data.is_Generic() )
- {
- auto ty_unit_ptr = ::HIR::TypeRef::new_borrow( e.type, ::HIR::TypeRef::new_unit() );
- if( se.dst.is_Temporary() && state.get_lvalue_type(tmp, se.dst) == ty_unit_ptr )
- {
- // Assigning fat pointer to a &() temporary, only happens if this has already happend
- }
- else
- {
- // Unwrap field accesses, next lvalue should be a deref
- const ::MIR::LValue* lv = &e.val;
- while( lv->is_Field() )
- lv = &*lv->as_Field().val;
- MIR_ASSERT(state, lv->is_Deref(), "Access of !Sized field not via a deref");
-
- const auto& dst_val_lval = *lv;
-
- auto meta_rval = ::MIR::RValue::make_DstMeta({ dst_val_lval.clone() });
- // TODO: How can the thin pointer to the field be obtained without tripping this twice?
- auto ptr_rval = mv$( se.src );
-
- // TODO: Get the metadata type.
- auto meta_ty = ::HIR::TypeRef( ::HIR::CoreType::Usize );
- auto meta_lval = mutator.in_temporary( mv$(meta_ty), mv$(meta_rval) );
-
- // HACK: Store the pointer as &()
- auto ptr_lval = mutator.in_temporary( mv$(ty_unit_ptr), mv$(ptr_rval) );
- se.src = ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(meta_lval) });
- }
- }
- }
-
+ // Fix up RValue::Cast into coercions
if( se.src.is_Cast() )
{
auto& e = se.src.as_Cast();
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 82b78dd8..7bdce493 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -953,22 +953,38 @@ namespace {
}
),
(Borrow,
- emit_lvalue(e.dst);
- m_of << " = ";
+ ::HIR::TypeRef tmp;
+ const auto& ty = mir_res.get_lvalue_type(tmp, ve.val);
bool special = false;
// If the inner value has type [T] or str, create DST based on inner pointer and existing metadata
- TU_IFLET(::MIR::LValue, ve.val, Deref, e,
- ::HIR::TypeRef tmp;
- const auto& ty = mir_res.get_lvalue_type(tmp, ve.val); // NOTE: Checks the result of the deref
+ TU_IFLET(::MIR::LValue, ve.val, Deref, le,
if( metadata_type(ty) != MetadataType::None ) {
- emit_lvalue(*e.val);
+ emit_lvalue(e.dst);
+ m_of << " = ";
+ emit_lvalue(*le.val);
special = true;
}
)
- // TODO: Magic for taking a &-ptr to unsized field of a struct.
+ // Magic for taking a &-ptr to unsized field of a struct.
// - Needs to get metadata from bottom-level pointer.
+ else TU_IFLET(::MIR::LValue, ve.val, Field, le,
+ if( metadata_type(ty) != MetadataType::None ) {
+ const ::MIR::LValue* base_val = &*le.val;
+ while(base_val->is_Field())
+ base_val = &*base_val->as_Field().val;
+ MIR_ASSERT(mir_res, base_val->is_Deref(), "DST access must be via a deref");
+ const ::MIR::LValue& base_ptr = *base_val->as_Deref().val;
+
+ // Construct the new DST
+ emit_lvalue(e.dst); m_of << ".META = "; emit_lvalue(base_ptr); m_of << ".META;\n\t";
+ emit_lvalue(e.dst); m_of << ".PTR = &"; emit_lvalue(ve.val);
+ special = true;
+ }
+ )
if( !special )
{
+ emit_lvalue(e.dst);
+ m_of << " = ";
m_of << "& "; emit_lvalue(ve.val);
}
),