summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/trans/codegen.cpp35
-rw-r--r--src/trans/codegen.hpp1
-rw-r--r--src/trans/codegen_c.cpp34
-rw-r--r--src/trans/enumerate.cpp222
-rw-r--r--src/trans/trans_list.hpp3
5 files changed, 187 insertions, 108 deletions
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp
index 8b4a1b85..3cb49887 100644
--- a/src/trans/codegen.cpp
+++ b/src/trans/codegen.cpp
@@ -23,22 +23,29 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons
// - Emit in the order they're needed.
for(const auto& ty : list.m_types)
{
- TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Path, te,
- TU_MATCHA( (te.binding), (tpb),
- (Unbound, throw ""; ),
- (Opaque, throw ""; ),
- (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);
+ if( ty.second )
+ {
+ codegen->emit_type_proto(ty.first);
+ }
+ else
+ {
+ TU_IFLET( ::HIR::TypeRef::Data, ty.first.m_data, Path, te,
+ TU_MATCHA( (te.binding), (tpb),
+ (Unbound, throw ""; ),
+ (Opaque, throw ""; ),
+ (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);
+ codegen->emit_type(ty.first);
+ }
}
// 2. Emit function prototypes
diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp
index e14a8e81..984c4742 100644
--- a/src/trans/codegen.hpp
+++ b/src/trans/codegen.hpp
@@ -30,6 +30,7 @@ public:
// Called on all types directly mentioned (e.g. variables, arguments, and fields)
// - Inner-most types are visited first.
+ virtual void emit_type_proto(const ::HIR::TypeRef& ) {}
virtual void emit_type(const ::HIR::TypeRef& ) {}
// Called when a TypeRef::Path is encountered (after visiting inner types)
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 7bdce493..b73b4d37 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -73,6 +73,40 @@ namespace {
<< "}\n";
}
+ void emit_type_proto(const ::HIR::TypeRef& ty) override
+ {
+ TRACE_FUNCTION_F(ty);
+ TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Tuple, te,
+ // TODO: Pre-define tuple name
+ )
+ else TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Function, te,
+ // TODO: Pre-define function type name
+ )
+ else TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Array, te,
+ // TODO: Pre-define array type name
+ )
+ else TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Path, te,
+ TU_MATCHA( (te.binding), (tpb),
+ (Unbound, throw ""; ),
+ (Opaque, throw ""; ),
+ (Struct,
+ m_of << "struct s_" << Trans_Mangle(te.path) << ";\n";
+ ),
+ (Union,
+ m_of << "union u_" << Trans_Mangle(te.path) << ";\n";
+ ),
+ (Enum,
+ m_of << "struct e_" << Trans_Mangle(te.path) << ";\n";
+ )
+ )
+ )
+ else if( ty.m_data.is_ErasedType() ) {
+ // TODO: Is this actually a bug?
+ return ;
+ }
+ else {
+ }
+ }
void emit_type(const ::HIR::TypeRef& ty) override
{
::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "type " << ty;), ::HIR::TypeRef(), {}, *(::MIR::Function*)nullptr };
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index d7ed1c6c..25513c17 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -156,12 +156,12 @@ namespace {
{
const ::HIR::Crate& m_crate;
::StaticTraitResolve m_resolve;
- ::std::vector< ::HIR::TypeRef>& out_list;
+ ::std::vector< ::std::pair< ::HIR::TypeRef, bool> >& out_list;
- ::std::set< ::HIR::TypeRef> visited;
+ ::std::map< ::HIR::TypeRef, bool > visited;
::std::set< const ::HIR::TypeRef*, PtrComp> active_set;
- TypeVisitor(const ::HIR::Crate& crate, ::std::vector< ::HIR::TypeRef>& out_list):
+ TypeVisitor(const ::HIR::Crate& crate, ::std::vector< ::std::pair< ::HIR::TypeRef, bool > >& out_list):
m_crate(crate),
m_resolve(crate),
out_list(out_list)
@@ -244,105 +244,137 @@ namespace {
}
}
- void visit_type(const ::HIR::TypeRef& ty)
+ enum class Mode {
+ Shallow,
+ Normal,
+ Deep,
+ };
+
+ void visit_type(const ::HIR::TypeRef& ty, Mode mode = Mode::Normal)
{
- // Already done
- if( visited.find(ty) != visited.end() )
- return ;
-
- if( active_set.find(&ty) != active_set.end() ) {
- // TODO: Handle recursion
- DEBUG("- Type recursion with " << ty);
- return ;
+ // If the type has already been visited, AND either this is a shallow visit, or the previous wasn't
+ {
+ auto it = visited.find(ty);
+ if( it != visited.end() )
+ {
+ if( it->second == false || mode == Mode::Shallow )
+ {
+ // Return early
+ return ;
+ }
+ DEBUG("-- " << ty << " already visited as shallow");
+ it->second = false;
+ }
}
- active_set.insert( &ty );
+ TRACE_FUNCTION_F(ty << " - " << (mode == Mode::Shallow ? "Shallow" : (mode == Mode::Normal ? "Normal" : "Deep")));
- TU_MATCHA( (ty.m_data), (te),
- // Impossible
- (Infer,
- ),
- (Generic,
- BUG(Span(), "Generic type hit in enumeration - " << ty);
- ),
- (ErasedType,
- //BUG(Span(), "ErasedType hit in enumeration - " << ty);
- ),
- (Closure,
- BUG(Span(), "Closure type hit in enumeration - " << ty);
- ),
- // Nothing to do
- (Diverge,
- ),
- (Primitive,
- ),
- // Recursion!
- (Path,
- TU_MATCHA( (te.binding), (tpb),
- (Unbound,
- BUG(Span(), "Unbound type hit in enumeration - " << ty);
+ if( mode != Mode::Shallow )
+ {
+ if( active_set.find(&ty) != active_set.end() ) {
+ // TODO: Handle recursion
+ DEBUG("- Type recursion with " << ty);
+ return ;
+ }
+ active_set.insert( &ty );
+
+ TU_MATCHA( (ty.m_data), (te),
+ // Impossible
+ (Infer,
),
- (Opaque,
- BUG(Span(), "Opaque type hit in enumeration - " << ty);
+ (Generic,
+ BUG(Span(), "Generic type hit in enumeration - " << ty);
),
- (Struct,
- visit_struct(te.path.m_data.as_Generic(), *tpb);
+ (ErasedType,
+ //BUG(Span(), "ErasedType hit in enumeration - " << ty);
),
- (Union,
- visit_union(te.path.m_data.as_Generic(), *tpb);
+ (Closure,
+ BUG(Span(), "Closure type hit in enumeration - " << ty);
),
- (Enum,
- visit_enum(te.path.m_data.as_Generic(), *tpb);
+ // Nothing to do
+ (Diverge,
+ ),
+ (Primitive,
+ ),
+ // Recursion!
+ (Path,
+ if( const auto* p = m_resolve.is_type_owned_box(ty) )
+ {
+ visit_type(*p);
+ }
+ TU_MATCHA( (te.binding), (tpb),
+ (Unbound,
+ BUG(Span(), "Unbound type hit in enumeration - " << ty);
+ ),
+ (Opaque,
+ BUG(Span(), "Opaque type hit in enumeration - " << ty);
+ ),
+ (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();
- }
+ ),
+ (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);
+ visit_type( ::HIR::TypeRef( ::HIR::GenericPath(vtable_ty_spath, mv$(vtable_params)), &vtable_ref ) );
+ ),
+ (Array,
+ visit_type(*te.inner, mode);
+ ),
+ (Slice,
+ visit_type(*te.inner, mode);
+ ),
+ (Borrow,
+ visit_type(*te.inner, mode != Mode::Deep ? Mode::Shallow : Mode::Deep);
+ ),
+ (Pointer,
+ visit_type(*te.inner, mode != Mode::Deep ? Mode::Shallow : Mode::Deep);
+ ),
+ (Tuple,
+ for(const auto& sty : te)
+ visit_type(sty, mode);
+ ),
+ (Function,
+ // TODO: Should shallow=true for these too?
+ visit_type(*te.m_rettype, mode);
+ for(const auto& sty : te.m_arg_types)
+ visit_type(sty, mode);
+ )
)
- )
- active_set.erase( active_set.find(&ty) );
+ active_set.erase( active_set.find(&ty) );
+ }
- visited.insert( ty.clone() );
- out_list.push_back( ty.clone() );
- DEBUG("Add type " << ty);
+ bool shallow = (mode == Mode::Shallow);
+ {
+ auto rv = visited.insert( ::std::make_pair(ty.clone(), shallow) );
+ if( !rv.second && ! shallow )
+ {
+ rv.first->second = false;
+ }
+ }
+ out_list.push_back( ::std::make_pair(ty.clone(), shallow) );
+ DEBUG("Add type " << ty << (shallow ? " (Shallow)": ""));
}
};
}
@@ -374,9 +406,9 @@ void Trans_Enumerate_Types(EnumState& state)
{
const auto& mir = *fcn.m_code.m_mir;
for(const auto& ty : mir.named_variables)
- tv.visit_type(pp.monomorph(tv.m_resolve, ty));
+ tv.visit_type(pp.monomorph(tv.m_resolve, ty), TypeVisitor::Mode::Deep);
for(const auto& ty : mir.temporaries)
- tv.visit_type(pp.monomorph(tv.m_resolve, ty));
+ tv.visit_type(pp.monomorph(tv.m_resolve, ty), TypeVisitor::Mode::Deep);
}
}
state.fcns_to_type_visit.clear();
@@ -394,7 +426,11 @@ void Trans_Enumerate_Types(EnumState& state)
constructors_added = false;
for(unsigned int i = types_count; i < state.rv.m_types.size(); i ++ )
{
- const auto& ty = state.rv.m_types[i];
+ const auto& ent = state.rv.m_types[i];
+ // Shallow? Skip.
+ if( ent.second )
+ continue ;
+ const auto& ty = ent.first;
if( ty.m_data.is_Path() )
{
const auto& te = ty.m_data.as_Path();
diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp
index 58a6030d..eed91551 100644
--- a/src/trans/trans_list.hpp
+++ b/src/trans/trans_list.hpp
@@ -59,7 +59,8 @@ public:
::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;
+ // .second is `true` if this is a from a reference to the type
+ ::std::vector< ::std::pair<::HIR::TypeRef, bool> > m_types;
TransList_Function* add_function(::HIR::Path p);
TransList_Static* add_static(::HIR::Path p);