diff options
author | John Hodge <tpg@mutabah.net> | 2018-08-04 15:35:46 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-08-04 15:36:26 +0800 |
commit | cd56b774f425b0c842556c3ddeeba708b0fe309f (patch) | |
tree | 2000d80c60c67e4f2d4f0d1906a8e0793e478ec5 | |
parent | 5ad533aca561e3daaaf5c7e492ccc5b6a3c99d1b (diff) | |
download | mrust-cd56b774f425b0c842556c3ddeeba708b0fe309f.tar.gz |
Trans - Add auto-generated Clone impls (only for Copy types currently)
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 7 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 8 | ||||
-rw-r--r-- | src/mir/mir_ptr.hpp | 9 | ||||
-rw-r--r-- | src/trans/auto_impls.cpp | 130 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 11 | ||||
-rw-r--r-- | src/trans/main_bindings.hpp | 2 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 6 |
9 files changed, 170 insertions, 10 deletions
@@ -115,7 +115,7 @@ OBJ += mir/check.o mir/cleanup.o mir/optimise.o OBJ += mir/check_full.o OBJ += hir/serialise.o hir/deserialise.o hir/serialise_lowlevel.o OBJ += trans/trans_list.o trans/mangling.o -OBJ += trans/enumerate.o trans/monomorphise.o trans/codegen.o +OBJ += trans/enumerate.o trans/auto_impls.o trans/monomorphise.o trans/codegen.o OBJ += trans/codegen_c.o trans/codegen_c_structured.o trans/codegen_mmir.o OBJ += trans/target.o trans/allocator.o diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 016d86a0..84c73bfb 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -105,8 +105,11 @@ bool StaticTraitResolve::find_impl( } } else if( TARGETVER_1_29 && trait_path == m_lang_Clone ) { - if( this->type_is_clone(sp, type) ) { - return found_cb( ImplRef(&type, &null_params, &null_assoc), false ); + if( type.m_data.is_Tuple() || type.m_data.is_Array() || type.m_data.is_Function() ) + { + if( this->type_is_clone(sp, type) ) { + return found_cb( ImplRef(&type, &null_params, &null_assoc), false ); + } } } else if( trait_path == m_lang_Sized ) { diff --git a/src/main.cpp b/src/main.cpp index 85afcb33..7104acb7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -657,6 +657,11 @@ int main(int argc, char *argv[]) } throw ::std::runtime_error("Invalid crate_type value"); }); + // - Generate automatic impls (mainly Clone for 1.29) + CompilePhaseV("Trans Auto Impls", [&]() { + // TODO: Drop glue generation? + Trans_AutoImpls(*hir_crate, items); + }); // - Generate monomorphised versions of all functions CompilePhaseV("Trans Monomorph", [&]() { Trans_Monomorphise_List(*hir_crate, items); }); // - Do post-monomorph inlining diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index dc3b78a7..84d60082 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1805,6 +1805,14 @@ namespace { mv$(values) })); } + if( fcn.m_abi == "platform-intrinsic" ) + { + m_builder.end_block(::MIR::Terminator::make_Call({ + next_block, panic_block, + res.clone(), ::MIR::CallTarget::make_Intrinsic({ "platform:"+gpath.m_path.m_components.back(), gpath.m_params.clone() }), + mv$(values) + })); + } // rustc has drop_in_place as a lang item, mrustc uses an intrinsic if( gpath.m_path == m_builder.crate().get_lang_item_path_opt("drop_in_place") ) diff --git a/src/mir/mir_ptr.hpp b/src/mir/mir_ptr.hpp index 9133dd44..27dd6b22 100644 --- a/src/mir/mir_ptr.hpp +++ b/src/mir/mir_ptr.hpp @@ -7,7 +7,6 @@ */ #pragma once - namespace MIR { class Function; @@ -32,10 +31,10 @@ public: void reset(); - ::MIR::Function* operator->() { return ptr; } - ::MIR::Function& operator*() { return *ptr; } - const ::MIR::Function* operator->() const { return ptr; } - const ::MIR::Function& operator*() const { return *ptr; } + ::MIR::Function* operator->() { if(!ptr) throw ""; return ptr; } + const ::MIR::Function* operator->() const { if(!ptr) throw ""; return ptr; } + ::MIR::Function& operator*() { if(!ptr) throw ""; return *ptr; } + const ::MIR::Function& operator*() const { if(!ptr) throw ""; return *ptr; } operator bool() const { return ptr != nullptr; } }; diff --git a/src/trans/auto_impls.cpp b/src/trans/auto_impls.cpp new file mode 100644 index 00000000..334d9eae --- /dev/null +++ b/src/trans/auto_impls.cpp @@ -0,0 +1,130 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * trans/auto_impls.cpp + * - Automatic trait/method impls + * + * Handles implementing Clone (when in 1.29 mode) + */ +#include "main_bindings.hpp" +#include "trans_list.hpp" +#include <hir/hir.hpp> +#include <mir/mir.hpp> +#include <hir_typeck/common.hpp> // monomorph +#include <hir_typeck/static.hpp> // StaticTraitResolve +#include <deque> +#include <algorithm> // find_if + +namespace { + struct State + { + ::HIR::Crate& crate; + StaticTraitResolve resolve; + const TransList& trans_list; + ::std::deque<::HIR::TypeRef> todo_list; + ::std::set<::HIR::TypeRef> done_list; + + ::HIR::SimplePath lang_Clone; + + State(::HIR::Crate& crate, const TransList& trans_list): + crate(crate), + resolve( crate ), + trans_list(trans_list) + { + lang_Clone = crate.get_lang_item_path(Span(), "clone"); + } + + void enqueue_type(const ::HIR::TypeRef& ty) { + if( this->trans_list.auto_clone_impls.count(ty) == 0 && this->done_list.count(ty) == 0 ) { + this->done_list.insert( ty.clone() ); + this->todo_list.push_back( ty.clone() ); + } + } + }; +} + +void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) +{ + Span sp; + TRACE_FUNCTION_F(ty); + + // Create MIR + ::MIR::Function mir_fcn; + if( state.resolve.type_is_copy(sp, ty) ) + { + ::MIR::BasicBlock bb; + bb.statements.push_back(::MIR::Statement::make_Assign({ + ::MIR::LValue::make_Return({}), + ::MIR::RValue::make_Use( ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({ 0 })) }) ) + })); + bb.terminator = ::MIR::Terminator::make_Return({}); + mir_fcn.blocks.push_back(::std::move( bb )); + } + else + { + TODO(Span(), "auto Clone for " << ty << " - Not Copy"); + } + + // Function + ::HIR::Function fcn { + /*m_save_code=*/false, + ::HIR::Linkage {}, + ::HIR::Function::Receiver::BorrowShared, + /*m_abi=*/ABI_RUST, + /*m_unsafe =*/false, + /*m_const=*/false, + ::HIR::GenericParams {}, + /*m_args=*/::make_vec1(::std::make_pair( + ::HIR::Pattern( ::HIR::PatternBinding(false, ::HIR::PatternBinding::Type::Move, "self", 0), ::HIR::Pattern::Data::make_Any({}) ), + ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()) + )), + /*m_variadic=*/false, + /*m_return=*/ty.clone(), + ::HIR::ExprPtr {} + }; + fcn.m_code.m_mir = ::MIR::FunctionPointer( new ::MIR::Function(mv$(mir_fcn)) ); + + // Impl + ::HIR::TraitImpl impl; + impl.m_type = mv$(ty); + impl.m_methods.insert(::std::make_pair( ::std::string("clone"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::std::move(fcn) } )); + + // Add impl to the crate + state.crate.m_trait_impls.insert(::std::make_pair( state.lang_Clone, ::std::move(impl) )); +} + +void Trans_AutoImpls(::HIR::Crate& crate, TransList& trans_list) +{ + State state { crate, trans_list }; + + // Generate for all + for(const auto& ty : trans_list.auto_clone_impls) + { + state.done_list.insert( ty.clone() ); + Trans_AutoImpl_Clone(state, ty.clone()); + } + + while( !state.todo_list.empty() ) + { + auto ty = ::std::move(state.todo_list.front()); + state.todo_list.pop_back(); + + Trans_AutoImpl_Clone(state, mv$(ty)); + } + + const auto impl_range = crate.m_trait_impls.equal_range( state.lang_Clone ); + for(const auto& ty : state.done_list) + { + // TODO: Find a way of turning a set into a vector so items can be erased. + + auto p = ::HIR::Path(ty.clone(), ::HIR::GenericPath(state.lang_Clone), "clone"); + //DEBUG("add_function(" << p << ")"); + auto e = trans_list.add_function(::std::move(p)); + + auto it = ::std::find_if( impl_range.first, impl_range.second, [&](const auto& i){ return i.second.m_type == ty; }); + assert( it->second.m_methods.size() == 1 ); + e->ptr = &it->second.m_methods.begin()->second.data; + } +} + diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 4e04ddf9..e16f9dcf 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -1209,7 +1209,7 @@ namespace { DEBUG("[get_ent_fullpath] Found " << impl_ref); //ASSERT_BUG(sp, !is_fuzz, "Fuzzy match not allowed here"); if( ! impl_ref.m_data.is_TraitImpl() ) { - DEBUG("Trans impl search found an invalid impl type"); + DEBUG("Trans impl search found an invalid impl type - " << impl_ref.m_data.tag_str()); is_dynamic = true; // TODO: This can only really happen if it's a trait object magic impl, which should become a vtable lookup. return true; @@ -1380,6 +1380,14 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co { // Must have been a dynamic dispatch request, just leave as-is } + // <* as Clone>::clone + else if( TARGETVER_1_29 && path_mono.m_data.is_UfcsKnown() && path_mono.m_data.as_UfcsKnown().trait == state.crate.get_lang_item_path_opt("clone") ) + { + const auto& pe = path_mono.m_data.as_UfcsKnown(); + ASSERT_BUG(sp, pe.item == "clone", ""); + // Add this type to a list of types that will have the impl auto-generated + state.rv.auto_clone_impls.insert( pe.type->clone() ); + } else { BUG(sp, "AutoGenerate returned for unknown path type - " << path_mono); @@ -1692,4 +1700,3 @@ void Trans_Enumerate_FillFrom(EnumState& state, const ::HIR::Static& item, Trans out_stat.ptr = &item; out_stat.pp = mv$(pp); } - diff --git a/src/trans/main_bindings.hpp b/src/trans/main_bindings.hpp index b938e8bf..096efe86 100644 --- a/src/trans/main_bindings.hpp +++ b/src/trans/main_bindings.hpp @@ -38,6 +38,8 @@ extern TransList Trans_Enumerate_Public(::HIR::Crate& crate); /// Re-run enumeration on monomorphised functions, removing now-unused items extern void Trans_Enumerate_Cleanup(const ::HIR::Crate& crate, TransList& list); +extern void Trans_AutoImpls(::HIR::Crate& crate, TransList& trans_list); + extern void Trans_Monomorphise_List(const ::HIR::Crate& crate, TransList& list); extern void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const ::HIR::Crate& crate, const TransList& list, bool is_executable); diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 48274f87..51e8af4b 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -52,6 +52,10 @@ struct TransList_Function Trans_Params pp; // If `pp.has_types` is true, the below is valid CachedFunction monomorphised; + + TransList_Function(): + ptr(nullptr) + {} }; struct TransList_Static { @@ -75,6 +79,8 @@ public: ::std::set< ::HIR::TypeRef> m_typeids; /// Required struct/enum constructor impls ::std::set< ::HIR::GenericPath> m_constructors; + // Automatic Clone impls + ::std::set< ::HIR::TypeRef> auto_clone_impls; // .second is `true` if this is a from a reference to the type ::std::vector< ::std::pair<::HIR::TypeRef, bool> > m_types; |