summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-01-02 18:25:00 +0800
committerJohn Hodge <tpg@mutabah.net>2017-01-02 18:25:00 +0800
commit63746ecbbf8a9e68a2c8ff1735032243ec29ee99 (patch)
treed900dcce638346e4be1d0b8dd2c866c3873257a3
parent379ca7a473e13fe242edcc847aaff341da58d9cc (diff)
downloadmrust-63746ecbbf8a9e68a2c8ff1735032243ec29ee99.tar.gz
MIR - Remove Deref from inputs to RValue::DstMeta/DstPtr
-rw-r--r--src/mir/check.cpp60
-rw-r--r--src/mir/cleanup.cpp22
-rw-r--r--src/mir/from_hir.cpp8
-rw-r--r--src/mir/from_hir.hpp3
-rw-r--r--src/mir/from_hir_match.cpp6
-rw-r--r--src/mir/mir_builder.cpp14
-rw-r--r--src/trans/codegen_c.cpp6
7 files changed, 94 insertions, 25 deletions
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 382694a7..ad8c9613 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -542,13 +542,65 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
// TODO: Check return type
),
(DstMeta,
- // TODO: Ensure that the input type is a: Generic, Array, or DST
- MIR_ASSERT(state, e.val.is_Deref(), "DstMeta requires a deref as input");
+ ::HIR::TypeRef tmp;
+ const auto& ty = state.get_lvalue_type(tmp, e.val);
+ const ::HIR::TypeRef* ity_p = nullptr;
+ if( (ity_p = state.is_type_owned_box(ty)) )
+ ;
+ else if( ty.m_data.is_Borrow() )
+ ity_p = &*ty.m_data.as_Borrow().inner;
+ else if( ty.m_data.is_Pointer() )
+ ity_p = &*ty.m_data.as_Pointer().inner;
+ else
+ MIR_BUG(state, "DstMeta requires a &-ptr as input, got " << ty);
+ const auto& ity = *ity_p;
+ if( ity.m_data.is_Generic() )
+ ;
+ else if( ity.m_data.is_Path() && ity.m_data.as_Path().binding.is_Opaque() )
+ ;
+ else if( ity.m_data.is_Array() )
+ ;
+ else if( ity.m_data.is_Slice() )
+ ;
+ else if( ity.m_data.is_TraitObject() )
+ ;
+ else if( ity.m_data.is_Path() )
+ {
+ // TODO: Check DST type of this path
+ }
+ else
+ {
+ MIR_BUG(state, "DstMeta on invalid type - " << ty);
+ }
// TODO: Check return type
),
(DstPtr,
- // TODO: Ensure that the input type is a DST
- MIR_ASSERT(state, e.val.is_Deref(), "DstPtr requires a deref as input");
+ ::HIR::TypeRef tmp;
+ const auto& ty = state.get_lvalue_type(tmp, e.val);
+ const ::HIR::TypeRef* ity_p = nullptr;
+ if( (ity_p = state.is_type_owned_box(ty)) )
+ ;
+ else if( ty.m_data.is_Borrow() )
+ ity_p = &*ty.m_data.as_Borrow().inner;
+ else if( ty.m_data.is_Pointer() )
+ ity_p = &*ty.m_data.as_Pointer().inner;
+ else
+ MIR_BUG(state, "DstPtr requires a &-ptr as input, got " << ty);
+ const auto& ity = *ity_p;
+ if( ity.m_data.is_Slice() )
+ ;
+ else if( ity.m_data.is_TraitObject() )
+ ;
+ else if( ity.m_data.is_Path() && ity.m_data.as_Path().binding.is_Opaque() )
+ ;
+ else if( ity.m_data.is_Path() )
+ {
+ // TODO: Check DST type of this path
+ }
+ else
+ {
+ MIR_BUG(state, "DstPtr on invalid type - " << ty);
+ }
// TODO: Check return type
),
(MakeDst,
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 3dc7f418..8056ae27 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -418,7 +418,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
// Allocate a temporary for the vtable pointer itself
auto vtable_lv = mutator.new_temporary( mv$(vtable_ty) );
// - Load the vtable and store it
- auto vtable_rval = ::MIR::RValue::make_DstMeta({ ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }) });
+ auto vtable_rval = ::MIR::RValue::make_DstMeta({ receiver_lvp.clone() });
mutator.push_statement( ::MIR::Statement::make_Assign({ vtable_lv.clone(), mv$(vtable_rval) }) );
auto fcn_lval = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Deref({ box$(vtable_lv) })), vtable_idx });
@@ -478,7 +478,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
{
return mutator.in_temporary(
::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit()),
- ::MIR::RValue::make_DstPtr({ ::MIR::LValue::make_Deref({ box$(lv) }) })
+ ::MIR::RValue::make_DstPtr({ mv$(lv) })
);
}
else
@@ -492,7 +492,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
}
else
{
- auto ptr_rval = ::MIR::RValue::make_DstPtr({ ::MIR::LValue::make_Deref({ box$(receiver_lvp.clone()) }) });
+ auto ptr_rval = ::MIR::RValue::make_DstPtr({ receiver_lvp.clone() });
auto ptr_lv = mutator.new_temporary( ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit()) );
mutator.push_statement( ::MIR::Statement::make_Assign({ ptr_lv.clone(), mv$(ptr_rval) }) );
@@ -618,8 +618,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
if( src_ty.m_data.is_TraitObject() )
{
out_src_is_dst = true;
- auto deref_ptr_val = ::MIR::LValue::make_Deref({ box$(ptr_value.clone()) });
- out_meta_val = ::MIR::RValue::make_DstMeta({ mv$(deref_ptr_val) });
+ out_meta_val = ::MIR::RValue::make_DstMeta({ ptr_value.clone() });
}
else
{
@@ -648,8 +647,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
if( source_is_dst )
{
auto ty_unit_ptr = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Shared, ::HIR::TypeRef::new_unit());
- auto deref_ptr_val = ::MIR::LValue::make_Deref({ box$(ptr_value) });
- auto thin_ptr_lval = mutator.in_temporary( mv$(ty_unit_ptr), ::MIR::RValue::make_DstPtr({ mv$(deref_ptr_val) }) );
+ auto thin_ptr_lval = mutator.in_temporary( mv$(ty_unit_ptr), ::MIR::RValue::make_DstPtr({ mv$(ptr_value) }) );
return ::MIR::RValue::make_MakeDst({ mv$(thin_ptr_lval), mv$(meta_lval) });
}
@@ -913,10 +911,16 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
MIR_Cleanup_LValue(state, mutator, re.val);
),
(DstMeta,
- MIR_Cleanup_LValue(state, mutator, re.val);
+ // HACK: Ensure that the box Deref conversion fires here.
+ auto v = ::MIR::LValue::make_Deref({ box$(re.val) });
+ MIR_Cleanup_LValue(state, mutator, v);
+ re.val = mv$( *v.as_Deref().val );
),
(DstPtr,
- MIR_Cleanup_LValue(state, mutator, re.val);
+ // HACK: Ensure that the box Deref conversion fires here.
+ auto v = ::MIR::LValue::make_Deref({ box$(re.val) });
+ MIR_Cleanup_LValue(state, mutator, v);
+ re.val = mv$( *v.as_Deref().val );
),
(MakeDst,
MIR_Cleanup_LValue(state, mutator, re.ptr_val);
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index e130f60e..6eb91386 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -320,7 +320,7 @@ 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({ 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).clone() }));
}
for(unsigned int i = 0; i < e.leading.size(); i ++)
@@ -1181,7 +1181,7 @@ namespace {
{
// HACK: FixedSizeArray uses `A: Unsize<[T]>` which will lead to the above code not working (as the size isn't known).
// - Maybe _Meta on the `&A` would work as a stopgap (since A: Sized, it won't collide with &[T] or similar)
- auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ::MIR::LValue::make_Deref({ box$(ptr_lval.clone()) }) }) );
+ auto size_lval = m_builder.lvalue_or_temp( node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), ::MIR::RValue::make_DstMeta({ ptr_lval.clone() }) );
m_builder.set_result( node.span(), ::MIR::RValue::make_MakeDst({ mv$(ptr_lval), mv$(size_lval) }) );
}
else
@@ -1227,9 +1227,7 @@ namespace {
limit_val = ::MIR::Constant( e.size_val );
),
(Slice,
- // TODO: What if this is of an unsized field? Later checks require that the inner be a LValue::Deref
- //ASSERT_BUG(node.span(), value.is_Deref(), "Slice index not via a deref");
- limit_val = ::MIR::RValue::make_DstMeta({ value.clone() });
+ limit_val = ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(node.m_value->span(), value).clone() });
)
)
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index dc11232e..b644e66f 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -226,6 +226,9 @@ private:
public:
void with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::function<void(const ::HIR::TypeRef&)> cb) const;
bool lvalue_is_copy(const Span& sp, const ::MIR::LValue& lv) const;
+
+ // Obtain the base fat poiner for a dst reference. Errors if it wasn't via a fat pointer
+ const ::MIR::LValue& get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const;
};
class MirConverter:
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index 008bef0c..3940a1c1 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -1775,7 +1775,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
// Compare length
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.len) ));
- auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
+ auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() }));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::EQ, mv$(test_lval) }));
auto len_succ_bb = builder.new_bb_unlinked();
@@ -1794,7 +1794,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
// Compare length
auto test_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue( ::MIR::Constant::make_Uint(re.min_len) ));
- auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
+ auto len_val = builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ builder.get_ptr_to_dst(sp, val).clone() }));
auto cmp_lval = builder.lvalue_or_temp(sp, ::HIR::CoreType::Bool, ::MIR::RValue::make_BinOp({ mv$(len_val), ::MIR::eBinOp::LT, mv$(test_lval) }));
auto len_succ_bb = builder.new_bb_unlinked();
@@ -3677,7 +3677,7 @@ void DecisionTreeGen::generate_branches_Slice(
ERROR(sp, E0000, "Non-exhaustive match over " << ty);
}
- auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ val.clone() }));
+ auto val_len = m_builder.lvalue_or_temp(sp, ::HIR::CoreType::Usize, ::MIR::RValue::make_DstMeta({ m_builder.get_ptr_to_dst(sp, val).clone() }));
// NOTE: Un-deref the slice
ASSERT_BUG(sp, val.is_Deref(), "slice matches must be passed a deref");
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index 6df64a0e..530ee0e9 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -1419,6 +1419,20 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv)
)
}
+const ::MIR::LValue& MirBuilder::get_ptr_to_dst(const Span& sp, const ::MIR::LValue& lv) const
+{
+ // Undo field accesses
+ const auto* lvp = &lv;
+ while(lvp->is_Field())
+ lvp = &*lvp->as_Field().val;
+
+ // TODO: Enum variants?
+
+ ASSERT_BUG(sp, lvp->is_Deref(), "Access of an unsized field without a dereference - " << lv);
+
+ return *lvp->as_Deref().val;
+}
+
// --------------------------------------------------------------------
ScopeHandle::~ScopeHandle()
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index a376721d..83e2ab8a 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -1267,15 +1267,13 @@ namespace {
(DstMeta,
emit_lvalue(e.dst);
m_of << " = ";
- MIR_ASSERT(mir_res, ve.val.is_Deref(), "DstMeta on non-deref");
- emit_lvalue(*ve.val.as_Deref().val);
+ emit_lvalue(ve.val);
m_of << ".META";
),
(DstPtr,
emit_lvalue(e.dst);
m_of << " = ";
- MIR_ASSERT(mir_res, ve.val.is_Deref(), "DstPtr on non-deref");
- emit_lvalue(*ve.val.as_Deref().val);
+ emit_lvalue(ve.val);
m_of << ".PTR";
),
(MakeDst,