summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/hir.cpp1
-rw-r--r--src/hir_expand/vtable.cpp2
-rw-r--r--src/mir/optimise.cpp2
-rw-r--r--src/trans/codegen.cpp9
-rw-r--r--src/trans/codegen.hpp2
-rw-r--r--src/trans/codegen_c.cpp46
-rw-r--r--src/trans/enumerate.cpp29
-rw-r--r--src/trans/trans_list.hpp4
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;
+ }
};