diff options
author | John Hodge <tpg@mutabah.net> | 2017-01-02 18:25:00 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2017-01-02 18:25:00 +0800 |
commit | 63746ecbbf8a9e68a2c8ff1735032243ec29ee99 (patch) | |
tree | d900dcce638346e4be1d0b8dd2c866c3873257a3 | |
parent | 379ca7a473e13fe242edcc847aaff341da58d9cc (diff) | |
download | mrust-63746ecbbf8a9e68a2c8ff1735032243ec29ee99.tar.gz |
MIR - Remove Deref from inputs to RValue::DstMeta/DstPtr
-rw-r--r-- | src/mir/check.cpp | 60 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 22 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 8 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 3 | ||||
-rw-r--r-- | src/mir/from_hir_match.cpp | 6 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 14 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 6 |
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, |