summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mir/cleanup.cpp40
-rw-r--r--src/mir/from_hir.cpp14
-rw-r--r--src/trans/codegen_c.cpp4
3 files changed, 49 insertions, 9 deletions
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 49739e28..c5a8c5b9 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -692,6 +692,7 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::
void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)
{
Span sp;
+ TRACE_FUNCTION_F(path);
::MIR::TypeResolve state { sp, resolve, FMT_CB(ss, ss << path;), ret_type, args, fcn };
MirMutator mutator { fcn, 0, 0 };
@@ -778,6 +779,45 @@ 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) });
+ }
+ }
+ }
+
if( se.src.is_Cast() )
{
auto& e = se.src.as_Cast();
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 14df55c6..75ff1619 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -1833,7 +1833,7 @@ namespace {
}
-::MIR::FunctionPointer LowerMIR(const StaticTraitResolve& resolve, const ::HIR::ExprPtr& ptr, const ::HIR::Function::args_t& args)
+::MIR::FunctionPointer LowerMIR(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, const ::HIR::ExprPtr& ptr, const ::HIR::Function::args_t& args)
{
TRACE_FUNCTION;
@@ -1862,7 +1862,7 @@ namespace {
}
::HIR::TypeRef ret;
- MIR_Cleanup(resolve, ::HIR::ItemPath(), fcn, args, ret);
+ MIR_Cleanup(resolve, path, fcn, args, ret);
return ::MIR::FunctionPointer(new ::MIR::Function(mv$(fcn)));
}
@@ -1889,7 +1889,7 @@ namespace {
this->visit_type( *e.inner );
DEBUG("Array size " << ty);
if( e.size ) {
- auto fcn = LowerMIR(m_resolve, *e.size, {});
+ auto fcn = LowerMIR(m_resolve, ::HIR::ItemPath(), *e.size, {});
e.size->m_mir = mv$(fcn);
}
)
@@ -1906,7 +1906,7 @@ namespace {
if( item.m_code )
{
DEBUG("Function code " << p);
- item.m_code.m_mir = LowerMIR(m_resolve, item.m_code, item.m_args);
+ item.m_code.m_mir = LowerMIR(m_resolve, p, item.m_code, item.m_args);
}
else
{
@@ -1917,14 +1917,14 @@ namespace {
if( item.m_value )
{
DEBUG("`static` value " << p);
- item.m_value.m_mir = LowerMIR(m_resolve, item.m_value, {});
+ item.m_value.m_mir = LowerMIR(m_resolve, p, item.m_value, {});
}
}
void visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) override {
if( item.m_value )
{
DEBUG("`const` value " << p);
- item.m_value.m_mir = LowerMIR(m_resolve, item.m_value, {});
+ item.m_value.m_mir = LowerMIR(m_resolve, p, item.m_value, {});
}
}
void visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) override {
@@ -1932,7 +1932,7 @@ namespace {
for(auto& var : item.m_variants)
{
TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- e.expr.m_mir = LowerMIR(m_resolve, e.expr, {});
+ e.expr.m_mir = LowerMIR(m_resolve, p + var.first, e.expr, {});
)
}
}
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 7951bb31..9e29d7bf 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -513,14 +513,14 @@ namespace {
(DstMeta,
emit_lvalue(e.dst);
m_of << " = ";
- assert( ve.val.is_Deref() );
+ MIR_ASSERT(mir_res, ve.val.is_Deref(), "DstMeta on non-deref");
emit_lvalue(*ve.val.as_Deref().val);
m_of << ".META";
),
(DstPtr,
emit_lvalue(e.dst);
m_of << " = ";
- assert( ve.val.is_Deref() );
+ MIR_ASSERT(mir_res, ve.val.is_Deref(), "DstPtr on non-deref");
emit_lvalue(*ve.val.as_Deref().val);
m_of << ".PTR";
),