diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-04 15:13:38 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-04 15:13:38 +0800 |
commit | bb2dfa78922acb5e1b8a2510412a8384acb99669 (patch) | |
tree | 34cbe4eb8464c9855e7fa21f168113e9d7594b00 | |
parent | e20f170181ac1b5bd101d57b2248288727b26e59 (diff) | |
download | mrust-bb2dfa78922acb5e1b8a2510412a8384acb99669.tar.gz |
Trans - Coming along
-rw-r--r-- | src/trans/codegen.cpp | 187 | ||||
-rw-r--r-- | src/trans/codegen.hpp | 15 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 172 | ||||
-rw-r--r-- | src/trans/mangling.cpp | 13 |
4 files changed, 363 insertions, 24 deletions
diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index 93032876..3aa6926a 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -8,16 +8,195 @@ #include "main_bindings.hpp" #include "trans_list.hpp" #include <hir/hir.hpp> +#include <mir/mir.hpp> #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 + { + CodeGenerator& codegen; + ::std::set< ::HIR::TypeRef> visited; + ::std::set< const ::HIR::TypeRef*, PtrComp> active_set; + + TypeVisitor(CodeGenerator& codegen): + 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, + ), + (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) { auto codegen = Trans_Codegen_GetGeneratorC(crate, outfile); // 1. Emit structure/type definitions. // - Emit in the order they're needed. + { + TypeVisitor tv { *codegen }; + for(const auto& ent : list.m_functions) + { + 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)); + } + } + } // 2. Emit function prototypes for(const auto& ent : list.m_functions) @@ -35,14 +214,16 @@ void Trans_Codegen(const ::std::string& outfile, const ::HIR::Crate& crate, cons for(const auto& ent : list.m_statics) { DEBUG("STATIC " << ent.first); + assert(ent.second->ptr); + const auto& stat = *ent.second->ptr; - if( ent.second->ptr ) + if( stat.m_value ) { - codegen->emit_static_ext(ent.first); + codegen->emit_static_local(ent.first, stat, ent.second->pp); } else { - codegen->emit_static_local(ent.first, *ent.second->ptr, ent.second->pp); + codegen->emit_static_ext(ent.first, stat, ent.second->pp); } } diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp index 84673eb0..b4a087be 100644 --- a/src/trans/codegen.hpp +++ b/src/trans/codegen.hpp @@ -28,12 +28,17 @@ public: virtual ~CodeGenerator() {} virtual void finalise() {} - virtual void emit_tuple(const ::HIR::GenericPath& p, const ::std::vector<::HIR::TypeRef>& ) {} - virtual void emit_struct(const ::HIR::GenericPath& p, const ::HIR::Struct& item) {} - virtual void emit_union(const ::HIR::GenericPath& p, const ::HIR::Union& item) {} - virtual void emit_enum(const ::HIR::GenericPath& p, const ::HIR::Enum& item) {} + // Called on all types directly mentioned (e.g. variables, arguments, and fields) + // - Inner-most types are visited first. + virtual void emit_type(const ::HIR::TypeRef& ) {} - virtual void emit_static_ext(const ::HIR::Path& p) {} + // Called when a TypeRef::Path is encountered (after visiting inner types) + virtual void emit_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) {} + 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_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) {} virtual void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) {} diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 6d331e65..d3c14ef5 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -10,18 +10,34 @@ #include <fstream> #include <hir/hir.hpp> #include <mir/mir.hpp> +#include <hir_typeck/static.hpp> namespace { class CodeGenerator_C: public CodeGenerator { const ::HIR::Crate& m_crate; + ::StaticTraitResolve m_resolve; ::std::ofstream m_of; public: CodeGenerator_C(const ::HIR::Crate& crate, const ::std::string& outfile): m_crate(crate), + m_resolve(crate), m_of(outfile) { + m_of + << "/*\n" + << " * AUTOGENERATED by mrustc\n" + << " */\n" + << "#include <stddef.h>\n" + << "#include <stdint.h>\n" + << "#include <stdbool.h>\n" + << "typedef uint32_t CHAR;\n" + << "typedef struct { } tUNIT;\n" + << "typedef struct { char* PTR; size_t META; } STR_PTR;\n" + << "typedef struct { void* PTR; size_t META; } SLICE_PTR;\n" + << "typedef struct { void* PTR; void* META; } TRAITOBJ_PTR;\n" + << "\n"; } ~CodeGenerator_C() {} @@ -30,13 +46,143 @@ namespace { { } - void emit_struct(const ::HIR::GenericPath& p, const ::HIR::Struct& item) override + void emit_type(const ::HIR::TypeRef& ty) override { + TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Tuple, te, + if( te.size() > 0 ) + { + m_of << "typedef struct {\n"; + for(unsigned int i = 0; i < te.size(); i++) + { + m_of << "\t"; + emit_ctype(te[i]); + m_of << " _" << i << ";\n"; + } + // TODO: Fields. + m_of << "} "; emit_ctype(ty); m_of << ";\n"; + } + ) + else TU_IFLET( ::HIR::TypeRef::Data, ty.m_data, Function, te, + m_of << "typedef "; + // TODO: ABI marker, need an ABI enum? + emit_ctype(*te.m_rettype); m_of << " (*"; emit_ctype(ty); m_of << ")("; + if( te.m_arg_types.size() == 0 ) + { + m_of << "void)"; + } + else + { + for(unsigned int i = 0; i < te.m_arg_types.size(); i ++) + { + if(i != 0) m_of << ","; + m_of << " "; + emit_ctype(te.m_arg_types[i]); + } + m_of << " )"; + } + m_of << ";\n"; + ) + else { + } + } + + void emit_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) override + { + ::HIR::TypeRef tmp; + auto monomorph = [&](const auto& x)->const auto& { + if( monomorphise_type_needed(x) ) { + tmp = monomorphise_type(sp, item.m_params, p.m_params, x); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return x; + } + }; + auto emit_struct_fld_ty = [&](const auto& ty) { + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Slice, te, + emit_ctype( monomorph(*te.inner) ); + m_of << "[]"; + ) + else { + emit_ctype( monomorph(ty) ); + } + }; m_of << "struct s_" << Trans_Mangle(p) << " {\n"; - m_of << "}\n"; + TU_MATCHA( (item.m_data), (e), + (Unit, + ), + (Tuple, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i]; + m_of << "\t"; + emit_struct_fld_ty(fld.ent); + m_of << " _" << i << ";\n"; + } + ), + (Named, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i].second; + m_of << "\t"; + emit_struct_fld_ty( fld.ent ); + m_of << " _" << i << ";\n"; + } + ) + ) + m_of << "};\n"; } //virtual void emit_union(const ::HIR::GenericPath& p, const ::HIR::Union& item); - //virtual void emit_enum(const ::HIR::GenericPath& p, const ::HIR::Enum& item); + void emit_enum(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Enum& item) override + { + ::HIR::TypeRef tmp; + auto monomorph = [&](const auto& x)->const auto& { + if( monomorphise_type_needed(x) ) { + tmp = monomorphise_type(sp, item.m_params, p.m_params, x); + m_resolve.expand_associated_types(sp, tmp); + return tmp; + } + else { + return x; + } + }; + m_of << "struct e_" << Trans_Mangle(p) << " {\n"; + m_of << "\tunsigned int TAG;\n"; + m_of << "\tunion {\n"; + for(unsigned int i = 0; i < item.m_variants.size(); i ++) + { + m_of << "\t\tstruct {\n"; + TU_MATCHA( (item.m_variants[i].second), (e), + (Unit, + ), + (Value, + // TODO: omit + ), + (Tuple, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i]; + m_of << "\t\t\t"; + emit_ctype( monomorph(fld.ent) ); + m_of << " _" << i << ";\n"; + } + ), + (Struct, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i]; + m_of << "\t\t\t"; + emit_ctype( monomorph(fld.second.ent) ); + m_of << " _" << i << ";\n"; + } + ) + ) + m_of << "\t\t} var_" << i << ";\n"; + } + m_of << "\t} DATA;\n"; + m_of << "};\n"; + } //virtual void emit_static_ext(const ::HIR::Path& p); //virtual void emit_static_local(const ::HIR::Path& p, const ::HIR::Static& item, const Trans_Params& params); @@ -257,7 +403,7 @@ namespace { if(j != 0) m_of << ","; m_of << " "; emit_lvalue(e.args[j]); } - m_of << " )\n"; + m_of << " );\n"; m_of << "\tgoto bb" << e.ret_block << ";\n"; ), (CallPath, @@ -266,7 +412,7 @@ namespace { if(j != 0) m_of << ","; m_of << " "; emit_lvalue(e.args[j]); } - m_of << " )\n"; + m_of << " );\n"; m_of << "\tgoto bb" << e.ret_block << ";\n"; ) ) @@ -318,8 +464,9 @@ namespace { m_of << "._" << e.field_index; ), (Deref, - m_of << "*"; + m_of << "(*"; emit_lvalue(*e.val); + m_of << ")"; ), (Index, m_of << "("; @@ -330,7 +477,7 @@ namespace { ), (Downcast, emit_lvalue(*e.val); - m_of << ".var_" << e.variant_index; + m_of << ".DATA.var_" << e.variant_index; ) ) } @@ -345,8 +492,8 @@ namespace { (Primitive, switch(te) { - case ::HIR::CoreType::Usize: m_of << "size_t"; break; - case ::HIR::CoreType::Isize: m_of << "ssize_t"; break; + case ::HIR::CoreType::Usize: m_of << "uintptr_t"; break; + case ::HIR::CoreType::Isize: m_of << "intptr_t"; break; case ::HIR::CoreType::U8: m_of << "uint8_t"; break; case ::HIR::CoreType::I8: m_of << "int8_t"; break; case ::HIR::CoreType::U16: m_of << "uint16_t"; break; @@ -360,7 +507,7 @@ namespace { case ::HIR::CoreType::F64: m_of << "double"; break; case ::HIR::CoreType::Bool: m_of << "bool"; break; - case ::HIR::CoreType::Char: m_of << "uin32_t"; break; + case ::HIR::CoreType::Char: m_of << "CHAR"; break; case ::HIR::CoreType::Str: BUG(Span(), "Raw str"); } @@ -394,7 +541,7 @@ namespace { BUG(Span(), "ErasedType in trans - " << ty); ), (Array, - m_of << "("; emit_ctype(*te.inner); m_of << ")[" << te.size_val << "]"; + emit_ctype(*te.inner); m_of << "[" << te.size_val << "]"; ), (Slice, BUG(Span(), "Raw slice object - " << ty); @@ -439,8 +586,7 @@ namespace { } ), (Function, - m_of << "void(void)*"; - //TODO(Span(), "Emit function pointer type - " << ty); + m_of << "t_" << Trans_Mangle(ty); ), (Closure, BUG(Span(), "Closure during trans - " << ty); diff --git a/src/trans/mangling.cpp b/src/trans/mangling.cpp index 339a5a35..6a175446 100644 --- a/src/trans/mangling.cpp +++ b/src/trans/mangling.cpp @@ -43,8 +43,12 @@ namespace { { return FMT_CB(ss, ss << "_ZN" << path.m_path.m_crate_name.size() << path.m_path.m_crate_name; - for(const auto& comp : path.m_path.m_components) - ss << comp.size() << comp; + for(const auto& comp : path.m_path.m_components) { + if( comp[0] == '#' ) + ss << (comp.size()-1+2) << "$H" << (comp.c_str()+1); + else + ss << comp.size() << comp; + } ss << emit_params(path.m_params); ); } @@ -64,7 +68,10 @@ namespace { ss << "_as_"; ss << Trans_Mangle(pe.trait); ss << "$aR"; - ss << pe.item; + if( pe.item[0] == '#' ) + ss << (pe.item.size()-1+2) << "$H" << (pe.item.c_str()+1); + else + ss << pe.item; ss << emit_params(pe.params); ); ), |