diff options
-rw-r--r-- | src/hir/hir.cpp | 1 | ||||
-rw-r--r-- | src/hir_expand/vtable.cpp | 2 | ||||
-rw-r--r-- | src/mir/optimise.cpp | 2 | ||||
-rw-r--r-- | src/trans/codegen.cpp | 9 | ||||
-rw-r--r-- | src/trans/codegen.hpp | 2 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 46 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 29 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 4 |
8 files changed, 94 insertions, 1 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index c23e86a0..0ae4a786 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -533,6 +533,7 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const auto it_t = bounds_t.begin(); for(auto it_o = bounds_o.begin(); it_o != bounds_o.end(); ++it_o) { + // TODO: `T: Foo<T>` is more specific than `T: Foo<U>` while( ::ord(*it_t, *it_o) == OrdLess && it_t != bounds_t.end() ) ++ it_t; if( it_t == bounds_t.end() || ::ord(*it_t, *it_o) > OrdEqual ) { diff --git a/src/hir_expand/vtable.cpp b/src/hir_expand/vtable.cpp index c36704ed..f12f8de5 100644 --- a/src/hir_expand/vtable.cpp +++ b/src/hir_expand/vtable.cpp @@ -232,6 +232,7 @@ namespace { ::HIR::Visitor::visit_trait_impl(trait_path, impl); + #if 0 // Check if the trait has a vtable, and if it does emit an associated static for it. const auto& tr = m_crate.get_trait_by_path(sp, trait_path); if(tr.m_value_indexes.size() > 0) @@ -266,6 +267,7 @@ namespace { ::HIR::Literal::make_List( mv$(vals) ) } } )); } + #endif } }; } diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp index f877ab88..601b1b18 100644 --- a/src/mir/optimise.cpp +++ b/src/mir/optimise.cpp @@ -134,6 +134,8 @@ void MIR_Optimise(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path // >> Propagate dead assignments // TODO: This requires kowing that doing so has no effect. // - Can use little heristics like a Call pointing to an assignment of its RV + // - Count the read/write count of a variable, if it's 1,1 then this optimisation is correct. + // - If the count is read=*,write=1 and the write is of an argument, replace with the argument. // GC pass on blocks and variables // - Find unused blocks, then delete and rewrite all references. diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index a4cec3e2..61c0d584 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -261,6 +261,15 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons } } + for(const auto& ent : list.m_vtables) + { + const auto& trait = ent.first.m_data.as_UfcsKnown().trait; + const auto& type = *ent.first.m_data.as_UfcsKnown().type; + DEBUG("VTABLE " << trait << " for " << type); + + codegen->emit_vtable(ent.first, crate.get_trait_by_path(Span(), trait.m_path)); + } + // 4. Emit function code for(const auto& ent : list.m_functions) diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp index b4a087be..b93f9d5d 100644 --- a/src/trans/codegen.hpp +++ b/src/trans/codegen.hpp @@ -37,6 +37,8 @@ public: virtual void emit_union(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Union& item) {} virtual void emit_enum(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Enum& item) {} + virtual void emit_vtable(const ::HIR::Path& p, const ::HIR::Trait& trait) {} + virtual void emit_static_ext(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {} virtual void emit_static_proto(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {} virtual void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params) {} diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index ed29a7eb..33402d9a 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -371,6 +371,52 @@ namespace { ) } + void emit_vtable(const ::HIR::Path& p, const ::HIR::Trait& trait) override + { + static Span sp; + const auto& trait_path = p.m_data.as_UfcsKnown().trait; + const auto& type = *p.m_data.as_UfcsKnown().type; + + { + auto vtable_sp = trait_path.m_path; + vtable_sp.m_components.back() += "#vtable"; + auto vtable_params = trait_path.m_params.clone(); + for(const auto& ty : trait.m_type_indexes) { + auto aty = ::HIR::TypeRef( ::HIR::Path( type.clone(), trait_path.clone(), ty.first ) ); + m_resolve.expand_associated_types(sp, aty); + vtable_params.m_types.push_back( mv$(aty) ); + } + const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_sp); + ::HIR::TypeRef vtable_ty( ::HIR::GenericPath(mv$(vtable_sp), mv$(vtable_params)), &vtable_ref ); + + emit_ctype(vtable_ty); + m_of << " " << Trans_Mangle(p) << " = {\n"; + } + + auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr); + + // TODO: Alignment and destructor + for(unsigned int i = 0; i < trait.m_value_indexes.size(); i ++ ) + { + if( i != 0 ) + m_of << ",\n"; + for(const auto& m : trait.m_value_indexes) + { + if( m.second.first != i ) + continue ; + + //ASSERT_BUG(sp, tr.m_values.at(m.first).is_Function(), "TODO: Handle generating vtables with non-function items"); + DEBUG("- " << m.second.first << " = " << m.second.second << " :: " << m.first); + + auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false); + // NOTE: `void*` cast avoids mismatched pointer type errors due to the receiver being &mut()/&() in the vtable + m_of << "\t(void*)" << Trans_Mangle( ::HIR::Path(type.clone(), mv$(gpath), m.first) ); + } + } + m_of << "\n"; + m_of << "\t};\n"; + } + void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) override { m_of << "// extern \"" << item.m_abi << "\" " << p << "\n"; diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 294cc228..737d1db2 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -18,6 +18,7 @@ void Trans_Enumerate_FillFrom(TransList& out, const ::HIR::Crate& crate, const ::HIR::Function& function, TransList_Function& fcn_out, Trans_Params pp={}); void Trans_Enumerate_FillFrom(TransList& out, const ::HIR::Crate& crate, const ::HIR::Static& stat, TransList_Static& stat_out, Trans_Params pp={}); +void Trans_Enumerate_FillFrom_VTable(TransList& out, const ::HIR::Crate& crate, ::HIR::Path vtable_path, const Trans_Params& pp); void Trans_Enumerate_FillFrom_Literal(TransList& out, const ::HIR::Crate& crate, const ::HIR::Literal& lit, const Trans_Params& pp); /// Enumerate trans items starting from `::main` (binary crate) @@ -277,6 +278,8 @@ namespace { DEBUG("Found impl" << impl.m_params.fmt_args() << " " << impl.m_type); return EntPtr { &it->second.data }; } + if( e.item == "#vtable" ) + return EntPtr::make_AutoGenerate( {} ); TODO(sp, "Associated static - " << path); ), (Function, @@ -335,7 +338,15 @@ void Trans_Enumerate_FillFrom_Path(TransList& out, const ::HIR::Crate& crate, co // This is returned either if the item is <T as U>::#vtable or if it's <(Trait) as Trait>::method if( path_mono.m_data.is_Generic() ) { - // TODO: Generate struct constructors? + // Leave generation of struct/enum constructors to codgen + } + else if( path_mono.m_data.as_UfcsKnown().item == "#vtable" ) + { + if( out.add_vtable( path_mono.clone(), {} ) ) + { + // Fill from the vtable + Trans_Enumerate_FillFrom_VTable(out,crate, mv$(path_mono), sub_pp); + } } else if( path_mono.m_data.as_UfcsKnown().type->m_data.is_TraitObject() ) { @@ -506,6 +517,22 @@ void Trans_Enumerate_FillFrom_MIR(TransList& out, const ::HIR::Crate& crate, con } } +void Trans_Enumerate_FillFrom_VTable(TransList& out, const ::HIR::Crate& crate, ::HIR::Path vtable_path, const Trans_Params& pp) +{ + static Span sp; + const auto& type = *vtable_path.m_data.as_UfcsKnown().type; + const auto& trait_path = vtable_path.m_data.as_UfcsKnown().trait; + const auto& tr = crate.get_trait_by_path(Span(), trait_path.m_path); + + auto monomorph_cb_trait = monomorphise_type_get_cb(sp, &type, &trait_path.m_params, nullptr); + for(const auto& m : tr.m_value_indexes) + { + DEBUG("- " << m.second.first << " = " << m.second.second << " :: " << m.first); + auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false); + Trans_Enumerate_FillFrom_Path(out,crate, ::HIR::Path(type.clone(), mv$(gpath), m.first), {}); + } +} + void Trans_Enumerate_FillFrom_Literal(TransList& out, const ::HIR::Crate& crate, const ::HIR::Literal& lit, const Trans_Params& pp) { TU_MATCHA( (lit), (e), diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index bca75dac..6cffa923 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -56,8 +56,12 @@ class TransList public: ::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Function> > m_functions; ::std::map< ::HIR::Path, ::std::unique_ptr<TransList_Static> > m_statics; + ::std::map< ::HIR::Path, Trans_Params> m_vtables; TransList_Function* add_function(::HIR::Path p); TransList_Static* add_static(::HIR::Path p); + bool add_vtable(::HIR::Path p, Trans_Params pp) { + return m_vtables.insert( ::std::make_pair( mv$(p), mv$(pp) ) ).second; + } }; |