diff options
-rw-r--r-- | src/trans/codegen.cpp | 227 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 27 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 258 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 2 |
4 files changed, 303 insertions, 211 deletions
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index 61c0d584..3f188dbf 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -14,222 +14,31 @@ #include "codegen.hpp" #include "monomorphise.hpp" -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; - CodeGenerator& codegen; - ::std::set< ::HIR::TypeRef> visited; - ::std::set< const ::HIR::TypeRef*, PtrComp> active_set; - - TypeVisitor(const ::HIR::Crate& crate, CodeGenerator& codegen): - m_crate(crate), - codegen(codegen) - {} - - 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) ); - ) - ) - codegen.emit_struct(sp, path, item); - } - void visit_union(const ::HIR::GenericPath& path, const ::HIR::Union& item) { - } - 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) ); - ) - ) - } - - codegen.emit_enum(sp, path, item); - } - - 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) ); - - codegen.emit_type(ty); - visited.insert( ty.clone() ); - } - }; -} - void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, const TransList& list) { + static Span sp; auto codegen = Trans_Codegen_GetGeneratorC(crate, outfile); // 1. Emit structure/type definitions. // - Emit in the order they're needed. + for(const auto& ty : list.m_types) { - TRACE_FUNCTION; - - TypeVisitor tv { crate, *codegen }; - for(const auto& ent : list.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 : list.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) ); - } + TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Path, te, + TU_MATCHA( (te.binding), (tpb), + (Unbound, ), + (Opaque, ), + (Struct, + codegen->emit_struct(sp, te.path.m_data.as_Generic(), *tpb); + ), + (Union, + codegen->emit_union(sp, te.path.m_data.as_Generic(), *tpb); + ), + (Enum, + codegen->emit_enum(sp, te.path.m_data.as_Generic(), *tpb); + ) + ) + ) + codegen->emit_type(ty); } // 2. Emit function prototypes diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index fff93530..ba3c568c 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -188,8 +188,18 @@ namespace { ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, {}, *(::MIR::Function*)nullptr }; m_mir_res = &mir_res; // - Drop Glue - // TOOD: If there's no fields, emit a #define-ed out destructor? + + if( item.m_markings.has_drop_impl ) { + m_of << "void " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(struct s_" << Trans_Mangle(p) << "*rv);\n"; + } + m_of << "void " << Trans_Mangle(drop_glue_path) << "(struct s_" << Trans_Mangle(p) << "* rv) {\n"; + + // If this type has an impl of Drop, call that impl + if( item.m_markings.has_drop_impl ) { + m_of << "\t" << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(rv);\n"; + } + auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }); auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 }); TU_MATCHA( (item.m_data), (e), @@ -277,8 +287,21 @@ namespace { auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone()); ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, {}, *(::MIR::Function*)nullptr }; m_mir_res = &mir_res; - // TOOD: If there's no fields, emit a #define-ed out destructor? + + + if( item.m_markings.has_drop_impl ) + { + m_of << "void " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(struct e_" << Trans_Mangle(p) << "*rv);\n"; + } + m_of << "void " << Trans_Mangle(drop_glue_path) << "(struct e_" << Trans_Mangle(p) << "* rv) {\n"; + + // If this type has an impl of Drop, call that impl + if( item.m_markings.has_drop_impl ) + { + m_of << "\t" << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "(rv);\n"; + } + auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }); auto fld_lv = ::MIR::LValue::make_Field({ box$(::MIR::LValue::make_Downcast({ box$(self), 0 })), 0 }); 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{}), diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 6cffa923..0ff2745c 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -57,6 +57,8 @@ 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; + + ::std::vector< ::HIR::TypeRef> m_types; TransList_Function* add_function(::HIR::Path p); TransList_Static* add_static(::HIR::Path p); |