diff options
author | John Hodge <tpg@mutabah.net> | 2018-01-27 16:02:21 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-01-27 16:02:21 +0800 |
commit | aeaeba5490d83937f647b544603c4da3b5c11dd4 (patch) | |
tree | 95c92e0b4f3dfdde16f67627601c1a9e46912435 | |
parent | 11d1bc911f80ed81ee4c96c8c1157d60d889d4d2 (diff) | |
download | mrust-aeaeba5490d83937f647b544603c4da3b5c11dd4.tar.gz |
Trans - Add "backend" for monomorphised MIR
-rw-r--r-- | src/hir/type.cpp | 7 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/mir/mir.cpp | 2 | ||||
-rw-r--r-- | src/trans/codegen.cpp | 11 | ||||
-rw-r--r-- | src/trans/codegen.hpp | 1 | ||||
-rw-r--r-- | src/trans/codegen_mmir.cpp | 766 | ||||
-rw-r--r-- | src/trans/main_bindings.hpp | 1 | ||||
-rw-r--r-- | vsproject/mrustc.vcxproj | 1 | ||||
-rw-r--r-- | vsproject/mrustc.vcxproj.filters | 3 |
10 files changed, 796 insertions, 4 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 36f09c9c..033e7bf5 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -105,8 +105,11 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const os << "*/"; ), (TraitObject, - os << "("; - os << e.m_trait; + os << "dyn ("; + if( e.m_trait.m_path != ::HIR::GenericPath() ) + { + os << e.m_trait; + } for(const auto& tr : e.m_markers) os << "+" << tr; if( e.m_lifetime.name != "" ) diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index 6e113d27..9d95038c 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -110,7 +110,7 @@ #define TU_IFLET(CLASS, VAR, TAG, NAME, ...) if(VAR.tag() == CLASS::TAG_##TAG) { auto& NAME = VAR.as_##TAG(); (void)&NAME; __VA_ARGS__ } // Evil hack: two for loops, the inner stops the outer after it's done. -#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc;) for(auto& NAME = VAR.as_##TAG(); tu_lc; tu_lc=false) +#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); tu_lc; tu_lc=false) //#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST) #define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST) diff --git a/src/main.cpp b/src/main.cpp index 7fa5e765..ea095367 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -185,6 +185,7 @@ struct ProgramParams bool full_validate_early = false; } debug; struct { + ::std::string codegen_type; ::std::string emit_build_command; } codegen; @@ -603,6 +604,7 @@ int main(int argc, char *argv[]) // - MIR Exportable (public generic, #[inline], or used by a either of those) // - Require codegen (public or used by an exported function) TransOptions trans_opt; + trans_opt.mode = params.codegen.codegen_type == "" ? "c" : params.codegen.codegen_type; trans_opt.build_command_file = params.codegen.emit_build_command; trans_opt.opt_level = params.opt_level; for(const char* libdir : params.lib_search_dirs ) { @@ -782,6 +784,10 @@ ProgramParams::ProgramParams(int argc, char *argv[]) get_optval(); this->codegen.emit_build_command = optval; } + else if( optname == "codegen-type" ) { + get_optval(); + this->codegen.codegen_type = optval; + } else if( optname == "emit-depfile" ) { get_optval(); this->emit_depfile = optval; diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index fb34357e..edb9170a 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -13,9 +13,11 @@ namespace MIR { (Int, os << (e.v < 0 ? "-" : "+"); os << (e.v < 0 ? -e.v : e.v); + os << " " << e.t; ), (Uint, os << e.v; + os << " " << e.t; ), (Float, os << e.v; diff --git a/src/trans/codegen.cpp b/src/trans/codegen.cpp index b3244072..f008a2b3 100644 --- a/src/trans/codegen.cpp +++ b/src/trans/codegen.cpp @@ -18,7 +18,16 @@ void Trans_Codegen(const ::std::string& outfile, const TransOptions& opt, const ::HIR::Crate& crate, const TransList& list, bool is_executable) { static Span sp; - auto codegen = Trans_Codegen_GetGeneratorC(crate, outfile); + ::std::unique_ptr<CodeGenerator> codegen; + + if( opt.mode == "monomir" ) + { + codegen = Trans_Codegen_GetGenerator_MonoMir(crate, outfile); + } + else + { + codegen = Trans_Codegen_GetGeneratorC(crate, outfile); + } // 1. Emit structure/type definitions. // - Emit in the order they're needed. diff --git a/src/trans/codegen.hpp b/src/trans/codegen.hpp index 65135d18..b769e350 100644 --- a/src/trans/codegen.hpp +++ b/src/trans/codegen.hpp @@ -56,4 +56,5 @@ public: extern ::std::unique_ptr<CodeGenerator> Trans_Codegen_GetGeneratorC(const ::HIR::Crate& crate, const ::std::string& outfile); +extern ::std::unique_ptr<CodeGenerator> Trans_Codegen_GetGenerator_MonoMir(const ::HIR::Crate& crate, const ::std::string& outfile); diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp new file mode 100644 index 00000000..590ec6ae --- /dev/null +++ b/src/trans/codegen_mmir.cpp @@ -0,0 +1,766 @@ +// +// +// +#include "codegen.hpp" +#include <hir_typeck/static.hpp> +#include <mir/helpers.hpp> +#include "mangling.hpp" +#include "target.hpp" + +#include <fstream> + +namespace +{ + template<typename T> + struct Fmt + { + const T& e; + Fmt(const T& e): + e(e) + { + } + }; + template<typename T> Fmt<T> fmt(const T& v) { return Fmt<T>(v); } + + ::std::ostream& operator<<(::std::ostream& os, const Fmt<::MIR::LValue>& x) + { + auto fmt_lhs = [](::std::ostream& os, const ::MIR::LValue& lv) { + if( lv.is_Deref() ) { + os << "(" << fmt(lv) << ")"; + } + else { + os << fmt(lv); + } + }; + switch(x.e.tag()) + { + case ::MIR::LValue::TAGDEAD: throw ""; + TU_ARM(x.e, Return, _e) + os << "RETURN"; + break; + TU_ARM(x.e, Local, e) + os << "var" << e; + break; + TU_ARM(x.e, Argument, e) + os << "arg" << e.idx; + break; + TU_ARM(x.e, Static, e) + os << e; + break; + TU_ARM(x.e, Deref, e) + os << "*" << fmt(*e.val); + break; + TU_ARM(x.e, Field, e) { + fmt_lhs(os, *e.val); + // Avoid `0.` existing in the output + if( e.val->is_Field() || e.val->is_Downcast() ) + os << " "; + os << "." << e.field_index; + } break; + TU_ARM(x.e, Index, e) { + fmt_lhs(os, *e.val); + os << "[" << fmt(*e.idx) << "]"; + } break; + TU_ARM(x.e, Downcast, e) { + fmt_lhs(os, *e.val); + os << "@" << e.variant_index; + } break; + } + return os; + } + ::std::ostream& operator<<(::std::ostream& os, const Fmt<::MIR::Param>& x) + { + switch(x.e.tag()) + { + case ::MIR::Param::TAGDEAD: throw ""; + TU_ARM(x.e, LValue, e) + os << fmt(e); + break; + TU_ARM(x.e, Constant, e) + os << e; + break; + } + return os; + } + + class CodeGenerator_MonoMir: + public CodeGenerator + { + enum class MetadataType { + None, + Slice, + TraitObject, + }; + + static Span sp; + + const ::HIR::Crate& m_crate; + ::StaticTraitResolve m_resolve; + + + ::std::string m_outfile_path; + ::std::ofstream m_of; + const ::MIR::TypeResolve* m_mir_res; + + public: + CodeGenerator_MonoMir(const ::HIR::Crate& crate, const ::std::string& outfile): + m_crate(crate), + m_resolve(crate), + m_outfile_path(outfile + ".mir"), + m_of(m_outfile_path) + { + for( const auto& crate : m_crate.m_ext_crates ) + { + m_of << "crate \"" << FmtEscaped(crate.second.m_path) << ".o.mir\";\n"; + } + } + + void finalise(bool is_executable, const TransOptions& opt) override + { + if( is_executable ) + { + m_of << "fn main(i32, *const *const i8): i32 {\n"; + m_of << "\t0: {\n"; + auto c_start_path = m_resolve.m_crate.get_lang_item_path_opt("mrustc-start"); + if( c_start_path == ::HIR::SimplePath() ) + { + m_of << "\tlet m: fn();"; + m_of << "\t0: {\n"; + m_of << "\t\tASSIGN m = " << Trans_Mangle( ::HIR::GenericPath(m_resolve.m_crate.get_lang_item_path(Span(), "mrustc-main")) ) << "\n"; + m_of << "\t\tCALL RETURN = " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(m, arg1, arg2) goto 1 else 1;\n"; + } + else + { + m_of << "\t0: {\n"; + m_of << "\t\tCALL RETURN = " << Trans_Mangle(::HIR::GenericPath(c_start_path)) << "(arg1, arg2) goto 1 else 1;\n"; + } + m_of << "\t}\n"; + m_of << "\t1: {\n"; + m_of << "\t\tRETURN}\n"; + m_of << "\t}\n"; + m_of << "}\n"; + } + + m_of.flush(); + m_of.close(); + } + + /* + void emit_box_drop_glue(::HIR::GenericPath p, const ::HIR::Struct& item) + { + auto struct_ty = ::HIR::TypeRef( p.clone(), &item ); + auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue"); + auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone()); + // - Drop Glue + const auto* ity = m_resolve.is_type_owned_box(struct_ty); + + auto inner_ptr = ::HIR::TypeRef::new_pointer( ::HIR::BorrowType::Unique, ity->clone() ); + auto box_free = ::HIR::GenericPath { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; + + ::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> > args; + args.push_back( ::std::make_pair( ::HIR::Pattern {}, mv$(inner_ptr) ) ); + + ::MIR::Function empty_fcn; + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, args, empty_fcn }; + m_mir_res = &mir_res; + m_of << "fn " << Trans_Mangle(drop_glue_path) << "(" << Trans_Mangle(p) << ") {\n"; + + // Obtain inner pointer + // TODO: This is very specific to the structure of the official liballoc's Box. + m_of << "\tlet arg1: "; emit_type(args[0].second); m_of << "\n"; + // Call destructor of inner data + emit_destructor_call( ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Argument({0})) }), *ity, true, 1); + // Emit a call to box_free for the type + m_of << "\t" << Trans_Mangle(box_free) << "(arg0);\n"; + + m_of << "}\n"; + m_mir_res = nullptr; + } + */ + + + void emit_type(const ::HIR::TypeRef& ty) override + { + TRACE_FUNCTION_F(ty); + ::MIR::Function empty_fcn; + ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "type " << ty;), ::HIR::TypeRef(), {}, empty_fcn }; + m_mir_res = &top_mir_res; + + if( const auto* te = ty.m_data.opt_Tuple() ) + { +#if 0 + if( te->size() > 0 ) + { + m_of << "typedef struct "; emit_ctype(ty); m_of << " {\n"; + for(unsigned int i = 0; i < te.size(); i++) + { + m_of << "\t"; + emit_ctype(te[i], FMT_CB(ss, ss << "_" << i;)); + m_of << ";\n"; + } + m_of << "} "; emit_ctype(ty); m_of << ";\n"; + } + + auto drop_glue_path = ::HIR::Path(ty.clone(), "#drop_glue"); + auto args = ::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> >(); + auto ty_ptr = ::HIR::TypeRef::new_pointer(::HIR::BorrowType::Owned, ty.clone()); + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), ty_ptr, args, empty_fcn }; + m_mir_res = &mir_res; + m_of << "static void " << Trans_Mangle(drop_glue_path) << "("; emit_ctype(ty); m_of << "* rv) {"; + auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }); + auto fld_lv = ::MIR::LValue::make_Field({ box$(self), 0 }); + for(const auto& ity : te) + { + emit_destructor_call(fld_lv, ity, /*unsized_valid=*/false, 1); + fld_lv.as_Field().field_index ++; + } + m_of << "}\n"; +#endif + } + else { + } + + m_mir_res = nullptr; + } + + void emit_struct(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Struct& item) override + { + ::MIR::Function empty_fcn; + ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "struct " << p;), ::HIR::TypeRef(), {}, empty_fcn }; + m_mir_res = &top_mir_res; + + bool is_vtable; { + const auto& lc = p.m_path.m_components.back(); + is_vtable = (lc.size() > 7 && ::std::strcmp(lc.c_str() + lc.size() - 7, "#vtable") == 0); + }; + + TRACE_FUNCTION_F(p); + ::HIR::TypeRef ty = ::HIR::TypeRef::new_path(p.clone(), &item); + + // HACK: For vtables, insert the alignment and size at the start + // TODO: Add this to the vtable in the HIR instead + if(is_vtable) + { + //m_of << "\tVTABLE_HDR hdr;\n"; + } + + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ty); + MIR_ASSERT(*m_mir_res, repr, "No repr for struct " << ty); + m_of << "type " << p << " {\n"; + m_of << "\tSIZE " << repr->size << ", ALIGN " << repr->align << ";\n"; + size_t ofs = 0; + for(const auto& e : repr->fields) + { + m_of << "\t" << e.offset << " = " << e.ty << ";\n"; + } + m_of << "}\n"; + + // TODO: Drop glue! +#if 0 + auto struct_ty = ::HIR::TypeRef(p.clone(), &item); + auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue"); + auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone()); + // - Drop Glue + + ::std::vector< ::std::pair<::HIR::Pattern,::HIR::TypeRef> > args; + if( item.m_markings.has_drop_impl ) { + // If the type is defined outside the current crate, define as static (to avoid conflicts when we define it) + if( p.m_path.m_crate_name != m_crate.m_crate_name ) + { + if( item.m_params.m_types.size() > 0 ) { + m_of << "static "; + } + else { + m_of << "extern "; + } + } + m_of << "tUNIT " << Trans_Mangle( ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") ) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ");\n"; + } + else if( m_resolve.is_type_owned_box(struct_ty) ) + { + m_box_glue_todo.push_back( ::std::make_pair( mv$(struct_ty.m_data.as_Path().path.m_data.as_Generic()), &item ) ); + m_of << "static void " << Trans_Mangle(drop_glue_path) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ");\n"; + return ; + } + + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, args, empty_fcn }; + m_mir_res = &mir_res; + m_of << "static void " << Trans_Mangle(drop_glue_path) << "("; emit_ctype(struct_ty_ptr, FMT_CB(ss, ss << "rv";)); m_of << ") {\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), + (Unit, + ), + (Tuple, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i]; + fld_lv.as_Field().field_index = i; + + emit_destructor_call(fld_lv, monomorph(fld.ent), true, 1); + } + ), + (Named, + for(unsigned int i = 0; i < e.size(); i ++) + { + const auto& fld = e[i].second; + fld_lv.as_Field().field_index = i; + + emit_destructor_call(fld_lv, monomorph(fld.ent), true, 1); + } + ) + ) + m_of << "}\n"; +#endif + m_mir_res = nullptr; + } + void emit_union(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Union& item) override + { + ::MIR::Function empty_fcn; + ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "union " << p;), ::HIR::TypeRef(), {}, empty_fcn }; + m_mir_res = &top_mir_res; + + TRACE_FUNCTION_F(p); + ::HIR::TypeRef ty = ::HIR::TypeRef::new_path(p.clone(), &item); + + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ty); + MIR_ASSERT(*m_mir_res, repr, "No repr for union " << ty); + m_of << "type " << p << " {\n"; + m_of << "\tSIZE " << repr->size << ", ALIGN " << repr->align << ";\n"; + size_t ofs = 0; + for(const auto& e : repr->fields) + { + m_of << "\t" << e.offset << " = " << e.ty << ";\n"; + } + m_of << "}\n"; + + // TODO: Drop glue! +#if 0 + // Drop glue (calls destructor if there is one) + auto item_ty = ::HIR::TypeRef(p.clone(), &item); + auto drop_glue_path = ::HIR::Path(item_ty.clone(), "#drop_glue"); + auto item_ptr_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, item_ty.clone()); + auto drop_impl_path = (item.m_markings.has_drop_impl ? ::HIR::Path(item_ty.clone(), m_resolve.m_lang_Drop, "drop") : ::HIR::Path(::HIR::SimplePath())); + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), item_ptr_ty, {}, empty_fcn }; + m_mir_res = &mir_res; + + if( item.m_markings.has_drop_impl ) + { + m_of << "tUNIT " << Trans_Mangle(drop_impl_path) << "(union u_" << Trans_Mangle(p) << "*rv);\n"; + } + + m_of << "static void " << Trans_Mangle(drop_glue_path) << "(union u_" << Trans_Mangle(p) << "* rv) {\n"; + if( item.m_markings.has_drop_impl ) + { + m_of << "\t" << Trans_Mangle(drop_impl_path) << "(rv);\n"; + } + m_of << "}\n"; +#endif + } + + void emit_enum(const Span& sp, const ::HIR::GenericPath& p, const ::HIR::Enum& item) override + { + ::MIR::Function empty_fcn; + ::MIR::TypeResolve top_mir_res { sp, m_resolve, FMT_CB(ss, ss << "enum " << p;), ::HIR::TypeRef(), {}, empty_fcn }; + m_mir_res = &top_mir_res; + + + TRACE_FUNCTION_F(p); + ::HIR::TypeRef ty = ::HIR::TypeRef::new_path(p.clone(), &item); + + const auto* repr = Target_GetTypeRepr(sp, m_resolve, ty); + MIR_ASSERT(*m_mir_res, repr, "No repr for enum " << ty); + m_of << "type " << p << " {\n"; + m_of << "\tSIZE " << repr->size << ", ALIGN " << repr->align << ";\n"; + size_t ofs = 0; + for(const auto& e : repr->fields) + { + m_of << "\t" << e.offset << " = " << e.ty << ";\n"; + } + switch(repr->variants.tag()) + { + case TypeRepr::VariantMode::TAGDEAD: throw ""; + TU_ARM(repr->variants, None, e) + break; + TU_ARM(repr->variants, Values, e) + for(auto v : e.values) + { + m_of << "\t[" << e.field.index << ", " << e.field.sub_fields << "] = \""; + for(size_t i = 0; i < e.field.size; i ++) + { + int val = (v >> (i*8)) & 0xFF; + //if( val == 0 ) + // m_of << "\\0"; + //else + if(val < 16) + m_of << ::std::hex << "\\x0" << val << ::std::dec; + else + m_of << ::std::hex << "\\x" << val << ::std::dec; + } + m_of << "\";\n"; + } + break; + TU_ARM(repr->variants, NonZero, e) { + m_of << "\t[" << e.field.index << ", " << e.field.sub_fields << "] = \""; + for(size_t i = 0; i < e.field.size; i ++) + { + m_of << "\\0"; + } + m_of << "\";\n"; + } break; + } + m_of << "}\n"; + +#if 0 + // --- + // - Drop Glue + // --- + auto struct_ty = ::HIR::TypeRef(p.clone(), &item); + auto drop_glue_path = ::HIR::Path(struct_ty.clone(), "#drop_glue"); + auto struct_ty_ptr = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Owned, struct_ty.clone()); + auto drop_impl_path = (item.m_markings.has_drop_impl ? ::HIR::Path(struct_ty.clone(), m_resolve.m_lang_Drop, "drop") : ::HIR::Path(::HIR::SimplePath())); + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << drop_glue_path;), struct_ty_ptr, {}, empty_fcn }; + m_mir_res = &mir_res; + + if( item.m_markings.has_drop_impl ) + { + m_of << "tUNIT " << Trans_Mangle(drop_impl_path) << "(struct e_" << Trans_Mangle(p) << "*rv);\n"; + } + + m_of << "static 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(drop_impl_path) << "(rv);\n"; + } + auto self = ::MIR::LValue::make_Deref({ box$(::MIR::LValue::make_Return({})) }); + + if( nonzero_path.size() > 0 ) + { + // TODO: Fat pointers? + m_of << "\tif( (*rv)._1"; emit_nonzero_path(nonzero_path); m_of << " ) {\n"; + emit_destructor_call( ::MIR::LValue::make_Field({ box$(self), 1 }), monomorph(item.m_data.as_Data()[1].type), false, 2 ); + m_of << "\t}\n"; + } + else if( const auto* e = item.m_data.opt_Data() ) + { + auto var_lv =::MIR::LValue::make_Downcast({ box$(self), 0 }); + + m_of << "\tswitch(rv->TAG) {\n"; + for(unsigned int var_idx = 0; var_idx < e->size(); var_idx ++) + { + var_lv.as_Downcast().variant_index = var_idx; + m_of << "\tcase " << var_idx << ":\n"; + emit_destructor_call(var_lv, monomorph( (*e)[var_idx].type ), false, 2); + m_of << "\tbreak;\n"; + } + m_of << "\t}\n"; + } + else + { + // Value enum + // Glue does nothing (except call the destructor, if there is one) + } + m_of << "}\n"; + + if( nonzero_path.size() ) + { + m_enum_repr_cache.insert( ::std::make_pair( p.clone(), mv$(nonzero_path) ) ); + } +#endif + m_mir_res = nullptr; + } + void emit_function_code(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params, bool is_extern_def, const ::MIR::FunctionPointer& code) override + { + TRACE_FUNCTION_F(p); + + ::MIR::TypeResolve::args_t arg_types; + for(const auto& ent : item.m_args) + arg_types.push_back(::std::make_pair( ::HIR::Pattern{}, params.monomorph(m_resolve, ent.second) )); + + ::HIR::TypeRef ret_type_tmp; + const auto& ret_type = monomorphise_fcn_return(ret_type_tmp, item, params); + + ::MIR::TypeResolve mir_res { sp, m_resolve, FMT_CB(ss, ss << p;), ret_type, arg_types, *code }; + m_mir_res = &mir_res; + + m_of << "fn " << p << "("; + m_of << "): " << ret_type << " {\n"; + for(unsigned int i = 0; i < code->locals.size(); i ++) { + DEBUG("var" << i << " : " << code->locals[i]); + m_of << "\tlet var" << i << ": " << code->locals[i] << ";\n"; + } + for(unsigned int i = 0; i < code->drop_flags.size(); i ++) { + m_of << "\tlet df" << i << " = " << code->drop_flags[i] << ";\n"; + } + + + for(unsigned int i = 0; i < code->blocks.size(); i ++) + { + TRACE_FUNCTION_F(p << " bb" << i); + + m_of << "\t" << i << ": {\n"; + + for(const auto& stmt : code->blocks[i].statements) + { + m_of << "\t\t"; + mir_res.set_cur_stmt(i, (&stmt - &code->blocks[i].statements.front())); + DEBUG(stmt); + switch(stmt.tag()) + { + case ::MIR::Statement::TAGDEAD: throw ""; + TU_ARM(stmt, Assign, se) { + m_of << "ASSIGN " << fmt(se.dst) << " = "; + switch(se.src.tag()) + { + case ::MIR::RValue::TAGDEAD: throw ""; + TU_ARM(se.src, Use, e) + m_of << "=" << fmt(e); + break; + TU_ARM(se.src, Constant, e) + m_of << e; + break; + TU_ARM(se.src, SizedArray, e) + m_of << "[" << fmt(e.val) << "; " << e.count << "]"; + break; + TU_ARM(se.src, Borrow, e) { + m_of << "&"; + switch(e.type) + { + case ::HIR::BorrowType::Shared: break; + case ::HIR::BorrowType::Unique: m_of << "mut "; break; + case ::HIR::BorrowType::Owned: m_of << "move "; break; + } + m_of << fmt(e.val); + } break; + TU_ARM(se.src, Cast, e) + m_of << "CAST " << fmt(e.val) << " as " << e.type; + break; + TU_ARM(se.src, BinOp, e) { + m_of << "BINOP " << fmt(e.val_l) << " "; + switch(e.op) + { + case ::MIR::eBinOp::ADD: m_of << "+"; break; + case ::MIR::eBinOp::ADD_OV: m_of << "+^"; break; + case ::MIR::eBinOp::SUB: m_of << "-"; break; + case ::MIR::eBinOp::SUB_OV: m_of << "-^"; break; + case ::MIR::eBinOp::MUL: m_of << "*"; break; + case ::MIR::eBinOp::MUL_OV: m_of << "*^"; break; + case ::MIR::eBinOp::DIV: m_of << "*"; break; + case ::MIR::eBinOp::DIV_OV: m_of << "*^"; break; + case ::MIR::eBinOp::MOD: m_of << "%"; break; + case ::MIR::eBinOp::BIT_OR: m_of << "|"; break; + case ::MIR::eBinOp::BIT_AND:m_of << "&"; break; + case ::MIR::eBinOp::BIT_XOR:m_of << "^"; break; + case ::MIR::eBinOp::BIT_SHR:m_of << ">>"; break; + case ::MIR::eBinOp::BIT_SHL:m_of << "<<"; break; + case ::MIR::eBinOp::NE: m_of << "!="; break; + case ::MIR::eBinOp::EQ: m_of << "=="; break; + case ::MIR::eBinOp::GT: m_of << ">" ; break; + case ::MIR::eBinOp::GE: m_of << ">="; break; + case ::MIR::eBinOp::LT: m_of << "<" ; break; + case ::MIR::eBinOp::LE: m_of << "<="; break; + } + m_of << " " << fmt(e.val_r); + } break; + TU_ARM(se.src, UniOp, e) { + m_of << "UNIOP "; + switch(e.op) + { + case ::MIR::eUniOp::INV: m_of << "!"; break; + case ::MIR::eUniOp::NEG: m_of << "-"; break; + } + m_of << " " << fmt(e.val); + } break; + TU_ARM(se.src, DstMeta, e) + m_of << "DSTMETA " << fmt(e.val); + break; + TU_ARM(se.src, DstPtr, e) + m_of << "DSTPTR " << fmt(e.val); + break; + TU_ARM(se.src, MakeDst, e) + m_of << "MAKEDST " << fmt(e.ptr_val) << ", " << fmt(e.ptr_val); + break; + TU_ARM(se.src, Variant, e) + m_of << "VARIANT " << e.path << " " << e.index << " " << fmt(e.val); + break; + TU_ARM(se.src, Array, e) { + m_of << "[ "; + for(const auto& v : e.vals) + { + m_of << fmt(v) << ", "; + } + m_of << "]"; + } break; + TU_ARM(se.src, Tuple, e) { + m_of << "( "; + for(const auto& v : e.vals) + { + m_of << fmt(v) << ", "; + } + m_of << ")"; + } break; + TU_ARM(se.src, Struct, e) { + m_of << "{ "; + for(const auto& v : e.vals) + { + m_of << fmt(v) << ", "; + } + m_of << "}: " << e.path; + } break; + } + } break; + TU_ARM(stmt, SetDropFlag, se) { + m_of << "SETFLAG df" << se.idx << " = "; + if( se.other == ~0u ) + { + m_of << se.new_val; + } + else + { + m_of << (se.new_val ? "" : "!") << "df" << se.other; + } + } break; + TU_ARM(stmt, Asm, se) { + m_of << "ASM ("; + for(const auto& v : se.outputs) + { + m_of << "\"" << v.first << "\" : " << fmt(v.second) << ", "; + } + m_of << ") = \"" << se.tpl << "\"("; + for(const auto& v : se.inputs) + { + m_of << "\"" << v.first << "\" : " << fmt(v.second) << ", "; + } + m_of << ") [" << se.flags << "]"; + } break; + TU_ARM(stmt, ScopeEnd, se) { + continue ; + } break; + TU_ARM(stmt, Drop, se) { + m_of << "DROP " << fmt(se.slot); + switch(se.kind) + { + case ::MIR::eDropKind::DEEP: + break; + case ::MIR::eDropKind::SHALLOW: + m_of << " SHALLOW"; + break; + } + if(se.flag_idx != ~0u) + { + m_of << " IF df" << se.flag_idx; + } + } break; + } + m_of << ";\n"; + } + + mir_res.set_cur_stmt_term(i); + const auto& term = code->blocks[i].terminator; + DEBUG("- " << term); + m_of << "\t\t"; + switch(term.tag()) + { + case ::MIR::Terminator::TAGDEAD: throw ""; + TU_ARM(term, Incomplete, _e) + m_of << "INCOMPLTE\n"; + break; + TU_ARM(term, Return, _e) + m_of << "RETURN\n"; + break; + TU_ARM(term, Diverge, _e) + m_of << "DIVERGE\n"; + break; + TU_ARM(term, Goto, e) + m_of << "GOTO " << e << "\n"; + break; + TU_ARM(term, Panic, e) + m_of << "PANIC " << e.dst << "\n"; + break; + TU_ARM(term, If, e) + m_of << "IF " << fmt(e.cond) << " goto " << e.bb0 << " else " << e.bb1 << "\n"; + break; + TU_ARM(term, Switch, e) { + m_of << "SWITCH " << fmt(e.val) << " { "; + m_of << e.targets; + m_of << " }\n"; + } break; + TU_ARM(term, SwitchValue, e) { + m_of << "SWITCHVALUE " << fmt(e.val) << " { "; + // TODO: Values. + //if( e.values.size() > 0 ) + //{ + // m_of << ", "; + //} + m_of << "_ = " << e.def_target; + m_of << " }\n"; + } break; + TU_ARM(term, Call, e) { + m_of << "CALL " << fmt(e.ret_val) << " = "; + switch(e.fcn.tag()) + { + case ::MIR::CallTarget::TAGDEAD: throw ""; + TU_ARM(e.fcn, Intrinsic, f) m_of << "\"" << f.name << "\"" << f.params; break; + TU_ARM(e.fcn, Value, f) m_of << "(" << fmt(f) << ")"; break; + TU_ARM(e.fcn, Path, f) m_of << f; break; + } + m_of << "("; + for(const auto& a : e.args) + { + m_of << fmt(a) << ", "; + } + m_of << ") goto " << e.ret_block << " else " << e.panic_block << "\n"; + } break; + } + m_of << "\t}\n"; + } + + m_of << "}\n"; + + + m_mir_res = nullptr; + } + + + private: + const ::HIR::TypeRef& monomorphise_fcn_return(::HIR::TypeRef& tmp, const ::HIR::Function& item, const Trans_Params& params) + { + if( visit_ty_with(item.m_return, [&](const auto& x){ return x.m_data.is_ErasedType() || x.m_data.is_Generic(); }) ) + { + tmp = clone_ty_with(Span(), item.m_return, [&](const auto& tpl, auto& out) { + TU_IFLET( ::HIR::TypeRef::Data, tpl.m_data, ErasedType, e, + out = params.monomorph(m_resolve, item.m_code.m_erased_types.at(e.m_index)); + return true; + ) + else if( tpl.m_data.is_Generic() ) { + out = params.get_cb()(tpl).clone(); + return true; + } + else { + return false; + } + }); + m_resolve.expand_associated_types(Span(), tmp); + return tmp; + } + else + { + return item.m_return; + } + } + }; + Span CodeGenerator_MonoMir::sp; +} + +::std::unique_ptr<CodeGenerator> Trans_Codegen_GetGenerator_MonoMir(const ::HIR::Crate& crate, const ::std::string& outfile) +{ + return ::std::unique_ptr<CodeGenerator>(new CodeGenerator_MonoMir(crate, outfile)); +}
\ No newline at end of file diff --git a/src/trans/main_bindings.hpp b/src/trans/main_bindings.hpp index 9c3bfd45..d78991d2 100644 --- a/src/trans/main_bindings.hpp +++ b/src/trans/main_bindings.hpp @@ -15,6 +15,7 @@ class Crate; struct TransOptions { + ::std::string mode = "c"; unsigned int opt_level = 0; bool emit_debug_info = false; ::std::string build_command_file; diff --git a/vsproject/mrustc.vcxproj b/vsproject/mrustc.vcxproj index 41d4b42a..c48d0444 100644 --- a/vsproject/mrustc.vcxproj +++ b/vsproject/mrustc.vcxproj @@ -244,6 +244,7 @@ <ClCompile Include="..\src\trans\codegen.cpp" /> <ClCompile Include="..\src\trans\codegen_c.cpp" /> <ClCompile Include="..\src\trans\codegen_c_structured.cpp" /> + <ClCompile Include="..\src\trans\codegen_mmir.cpp" /> <ClCompile Include="..\src\trans\enumerate.cpp" /> <ClCompile Include="..\src\trans\mangling.cpp" /> <ClCompile Include="..\src\trans\monomorphise.cpp" /> diff --git a/vsproject/mrustc.vcxproj.filters b/vsproject/mrustc.vcxproj.filters index 8a326741..6c0ba794 100644 --- a/vsproject/mrustc.vcxproj.filters +++ b/vsproject/mrustc.vcxproj.filters @@ -389,6 +389,9 @@ <ClCompile Include="..\src\expand\proc_macro.cpp"> <Filter>Source Files\expand</Filter> </ClCompile> + <ClCompile Include="..\src\trans\codegen_mmir.cpp"> + <Filter>Source Files\trans</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\src\common.hpp"> |