summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/trans/codegen.cpp227
-rw-r--r--src/trans/codegen_c.cpp27
-rw-r--r--src/trans/enumerate.cpp258
-rw-r--r--src/trans/trans_list.hpp2
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);