summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-08-04 15:35:46 +0800
committerJohn Hodge <tpg@mutabah.net>2018-08-04 15:36:26 +0800
commitcd56b774f425b0c842556c3ddeeba708b0fe309f (patch)
tree2000d80c60c67e4f2d4f0d1906a8e0793e478ec5
parent5ad533aca561e3daaaf5c7e492ccc5b6a3c99d1b (diff)
downloadmrust-cd56b774f425b0c842556c3ddeeba708b0fe309f.tar.gz
Trans - Add auto-generated Clone impls (only for Copy types currently)
-rw-r--r--Makefile2
-rw-r--r--src/hir_typeck/static.cpp7
-rw-r--r--src/main.cpp5
-rw-r--r--src/mir/from_hir.cpp8
-rw-r--r--src/mir/mir_ptr.hpp9
-rw-r--r--src/trans/auto_impls.cpp130
-rw-r--r--src/trans/enumerate.cpp11
-rw-r--r--src/trans/main_bindings.hpp2
-rw-r--r--src/trans/trans_list.hpp6
9 files changed, 170 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 5b21f186..f2067a9c 100644
--- a/Makefile
+++ b/Makefile
@@ -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;