summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-10 13:02:06 +0800
committerJohn Hodge <tpg@mutabah.net>2016-12-10 13:02:06 +0800
commit09b073ba0195218e9a9f7ce8a57bc019fd373567 (patch)
tree541d6715f7a69bc69145f43ff99e42f77ee552e0
parentedd6791bb8e16b2d05c57b732c9185af5409b6c0 (diff)
downloadmrust-09b073ba0195218e9a9f7ce8a57bc019fd373567.tar.gz
MIR Cleanup - Hacky inner deref of Box
-rw-r--r--src/mir/cleanup.cpp54
1 files changed, 43 insertions, 11 deletions
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 439f8f91..7297f402 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -429,17 +429,6 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::MIR::LValue& lval)
{
- if( lval.is_Deref() )
- {
- ::HIR::TypeRef tmp;
- const auto& ty = state.get_lvalue_type(tmp, lval);
- if( state.m_resolve.is_type_owned_box(ty) )
- {
- // TODO: Handle Box by extracting it to its pointer.
- // - Locate (or remember) which field in Box is the pointer, and replace the inner by that field
- }
- }
-
TU_MATCHA( (lval), (le),
(Variable,
),
@@ -465,6 +454,49 @@ void MIR_Cleanup_LValue(const ::MIR::TypeResolve& state, MirMutator& mutator, ::
MIR_Cleanup_LValue(state, mutator, *le.val);
)
)
+
+ // If this is a deref of Box, unpack and deref the inner pointer
+ if( lval.is_Deref() )
+ {
+ auto& le = lval.as_Deref();
+ ::HIR::TypeRef tmp;
+ const auto& ty = state.get_lvalue_type(tmp, *le.val);
+ if( state.m_resolve.is_type_owned_box(ty) )
+ {
+ // Handle Box by extracting it to its pointer.
+ // - Locate (or remember) which field in Box is the pointer, and replace the inner by that field
+ // > Dumb idea, assume it's always the first field. Keep accessing until located.
+
+ const auto* typ = &ty;
+ while( typ->m_data.is_Path() )
+ {
+ const auto& te = typ->m_data.as_Path();
+ MIR_ASSERT(state, te.binding.is_Struct(), "Box contained a non-struct");
+ const auto& str = *te.binding.as_Struct();
+ const ::HIR::TypeRef* ty_tpl = nullptr;
+ TU_MATCHA( (str.m_data), (se),
+ (Unit,
+ MIR_BUG(state, "Box contained a unit-like struct");
+ ),
+ (Tuple,
+ MIR_ASSERT(state, se.size() > 0, "Box contained an empty tuple struct");
+ ty_tpl = &se[0].ent;
+ ),
+ (Named,
+ MIR_ASSERT(state, se.size() > 0, "Box contained an empty named struct");
+ ty_tpl = &se[0].second.ent;
+ )
+ )
+ tmp = monomorphise_type(state.sp, str.m_params, te.path.m_data.as_Generic().m_params, *ty_tpl);
+ typ = &tmp;
+
+ auto new_lval = ::MIR::LValue::make_Field({ mv$(le.val), 0 });
+ le.val = box$(new_lval);
+ }
+ MIR_ASSERT(state, typ->m_data.is_Pointer(), "First non-path field in Box wasn't a pointer - " << *typ);
+ // We have reached the pointer. Good.
+ }
+ }
}
void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path, ::MIR::Function& fcn, const ::HIR::Function::args_t& args, const ::HIR::TypeRef& ret_type)