diff options
Diffstat (limited to 'src/trans/enumerate.cpp')
-rw-r--r-- | src/trans/enumerate.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index 737d1db2..ff1f3bdd 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -16,6 +16,8 @@ #include <hir/item_path.hpp> +void Trans_Enumerate_Types(TransList& out, const ::HIR::Crate& crate); +void Trans_Enumerate_FillFrom_Path(TransList& out, const ::HIR::Crate& crate, const ::HIR::Path& path, const Trans_Params& pp); 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); @@ -50,6 +52,9 @@ TransList Trans_Enumerate_Main(const ::HIR::Crate& crate) } // TODO: Search the trans list for external functions that refer to a named symbol, search for that defined elsewhere. + // - Not needed yet, there's a slow hack elsewhere + + Trans_Enumerate_Types(rv, crate); return rv; } @@ -95,10 +100,263 @@ TransList Trans_Enumerate_Public(const ::HIR::Crate& crate) Trans_Enumerate_Public_Mod(rv, crate, crate.m_root_module, ::HIR::SimplePath("",{})); + Trans_Enumerate_Types(rv, crate); + return rv; } namespace { + struct PtrComp + { + template<typename T> + bool operator()(const T* lhs, const T* rhs) const { return *lhs < *rhs; } + }; + + struct TypeVisitor + { + const ::HIR::Crate& m_crate; + ::std::vector< ::HIR::TypeRef>& out_list; + + ::std::set< ::HIR::TypeRef> visited; + ::std::set< const ::HIR::TypeRef*, PtrComp> active_set; + + TypeVisitor(const ::HIR::Crate& crate, ::std::vector< ::HIR::TypeRef>& out_list): + m_crate(crate), + out_list(out_list) + {} + + void visit_struct(const ::HIR::GenericPath& path, const ::HIR::Struct& item) { + static Span sp; + ::HIR::TypeRef tmp; + auto monomorph = [&](const auto& x)->const auto& { + if( monomorphise_type_needed(x) ) { + tmp = monomorphise_type(sp, item.m_params, path.m_params, x); + //m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return x; + } + }; + TU_MATCHA( (item.m_data), (e), + (Unit, + ), + (Tuple, + for(const auto& fld : e) { + visit_type( monomorph(fld.ent) ); + } + ), + (Named, + for(const auto& fld : e) + visit_type( monomorph(fld.second.ent) ); + ) + ) + } + void visit_union(const ::HIR::GenericPath& path, const ::HIR::Union& item) { + // TODO: . + } + void visit_enum(const ::HIR::GenericPath& path, const ::HIR::Enum& item) { + static Span sp; + ::HIR::TypeRef tmp; + auto monomorph = [&](const auto& x)->const auto& { + if( monomorphise_type_needed(x) ) { + tmp = monomorphise_type(sp, item.m_params, path.m_params, x); + //m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return x; + } + }; + for(const auto& variant : item.m_variants) + { + TU_MATCHA( (variant.second), (e), + (Unit, + ), + (Value, + ), + (Tuple, + for(const auto& ty : e) + visit_type( monomorph(ty.ent) ); + ), + (Struct, + for(const auto& fld : e) + visit_type( monomorph(fld.second.ent) ); + ) + ) + } + } + + void visit_type(const ::HIR::TypeRef& ty) + { + // Already done + if( visited.find(ty) != visited.end() ) + return ; + + if( active_set.find(&ty) != active_set.end() ) { + // TODO: Handle recursion + return ; + } + active_set.insert( &ty ); + + TU_MATCHA( (ty.m_data), (te), + // Impossible + (Infer, + ), + (Generic, + ), + (ErasedType, + ), + (Closure, + ), + // Nothing to do + (Diverge, + ), + (Primitive, + ), + // Recursion! + (Path, + TU_MATCHA( (te.binding), (tpb), + (Unbound, ), + (Opaque, ), + (Struct, + visit_struct(te.path.m_data.as_Generic(), *tpb); + ), + (Union, + visit_union(te.path.m_data.as_Generic(), *tpb); + ), + (Enum, + visit_enum(te.path.m_data.as_Generic(), *tpb); + ) + ) + ), + (TraitObject, + static Span sp; + // Ensure that the data trait's vtable is present + const auto& trait = *te.m_trait.m_trait_ptr; + + auto vtable_ty_spath = te.m_trait.m_path.m_path; + vtable_ty_spath.m_components.back() += "#vtable"; + const auto& vtable_ref = m_crate.get_struct_by_path(sp, vtable_ty_spath); + // Copy the param set from the trait in the trait object + ::HIR::PathParams vtable_params = te.m_trait.m_path.m_params.clone(); + // - Include associated types on bound + for(const auto& ty_b : te.m_trait.m_type_bounds) { + auto idx = trait.m_type_indexes.at(ty_b.first); + if(vtable_params.m_types.size() <= idx) + vtable_params.m_types.resize(idx+1); + vtable_params.m_types[idx] = ty_b.second.clone(); + } + + + visit_type( ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref ) ); + ), + (Array, + visit_type(*te.inner); + ), + (Slice, + visit_type(*te.inner); + ), + (Borrow, + visit_type(*te.inner); + ), + (Pointer, + visit_type(*te.inner); + ), + (Tuple, + for(const auto& sty : te) + visit_type(sty); + ), + (Function, + visit_type(*te.m_rettype); + for(const auto& sty : te.m_arg_types) + visit_type(sty); + ) + ) + active_set.erase( active_set.find(&ty) ); + + visited.insert( ty.clone() ); + out_list.push_back( ty.clone() ); + } + }; +} + +// Enumerate types required for the enumerated items +void Trans_Enumerate_Types(TransList& out, const ::HIR::Crate& crate) +{ + TypeVisitor tv { crate, out.m_types }; + + unsigned int types_count = 0; + bool constructors_added; + do + { + for(const auto& ent : out.m_functions) + { + TRACE_FUNCTION_F("Enumerate fn " << ent.first); + assert(ent.second->ptr); + const auto& fcn = *ent.second->ptr; + const auto& pp = ent.second->pp; + + tv.visit_type( pp.monomorph(crate, fcn.m_return) ); + for(const auto& arg : fcn.m_args) + tv.visit_type( pp.monomorph(crate, arg.second) ); + + if( fcn.m_code.m_mir ) + { + const auto& mir = *fcn.m_code.m_mir; + for(const auto& ty : mir.named_variables) + tv.visit_type(pp.monomorph(crate, ty)); + for(const auto& ty : mir.temporaries) + tv.visit_type(pp.monomorph(crate, ty)); + } + } + for(const auto& ent : out.m_statics) + { + TRACE_FUNCTION_F("Enumerate static " << ent.first); + assert(ent.second->ptr); + const auto& stat = *ent.second->ptr; + const auto& pp = ent.second->pp; + + tv.visit_type( pp.monomorph(crate, stat.m_type) ); + } + + constructors_added = false; + for(unsigned int i = types_count; i < out.m_types.size(); i ++ ) + { + const auto& ty = out.m_types[i]; + if( ty.m_data.is_Path() ) + { + const auto& te = ty.m_data.as_Path(); + const ::HIR::TraitMarkings* markings_ptr = nullptr; + TU_MATCHA( (te.binding), (tpb), + (Unbound, ), + (Opaque, ), + (Struct, + markings_ptr = &tpb->m_markings; + ), + (Union, + markings_ptr = &tpb->m_markings; + ), + (Enum, + markings_ptr = &tpb->m_markings; + ) + ) + ASSERT_BUG(Span(), markings_ptr, ""); + + if( markings_ptr->has_drop_impl ) + { + // Add the Drop impl to the codegen list + Trans_Enumerate_FillFrom_Path(out, crate, ::HIR::Path( ty.clone(), crate.get_lang_item_path(Span(), "drop"), "drop"), {}); + + constructors_added = true; + } + } + } + types_count = out.m_types.size(); + } while(constructors_added); +} + +namespace { TAGGED_UNION(EntPtr, NotFound, (NotFound, struct{}), (AutoGenerate, struct{}), |