summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-04 15:13:38 +0800
committerJohn Hodge <tpg@mutabah.net>2016-12-04 15:13:38 +0800
commitbb2dfa78922acb5e1b8a2510412a8384acb99669 (patch)
tree34cbe4eb8464c9855e7fa21f168113e9d7594b00 /src
parente20f170181ac1b5bd101d57b2248288727b26e59 (diff)
downloadmrust-bb2dfa78922acb5e1b8a2510412a8384acb99669.tar.gz
Trans - Coming along
Diffstat (limited to 'src')
-rw-r--r--src/trans/codegen.cpp187
-rw-r--r--src/trans/codegen.hpp15
-rw-r--r--src/trans/codegen_c.cpp172
-rw-r--r--src/trans/mangling.cpp13
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);
);
),