diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-11 12:17:17 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-11 12:17:17 +0800 |
commit | 5f22f9f6d48411d56d9999d9a7d2c64b1aa31e73 (patch) | |
tree | a5513e62de44aa6f0a3ae37fd0ebfa0a50f54a0e /src | |
parent | b556656fc9141c2d157b8da8fc95adaa16683e40 (diff) | |
download | mrust-5f22f9f6d48411d56d9999d9a7d2c64b1aa31e73.tar.gz |
Trans - Intrinsics (partially complete)
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 5 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 3 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 1 | ||||
-rw-r--r-- | src/mir/dump.cpp | 2 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 30 | ||||
-rw-r--r-- | src/mir/mir.cpp | 2 | ||||
-rw-r--r-- | src/mir/mir.hpp | 5 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 137 | ||||
-rw-r--r-- | src/trans/monomorphise.cpp | 5 | ||||
-rw-r--r-- | src/trans/trans_list.cpp | 9 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 1 |
11 files changed, 186 insertions, 14 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index f6b624c7..45a60887 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -997,7 +997,10 @@ namespace { #define _(x, ...) case ::MIR::CallTarget::TAG_##x: return ::MIR::CallTarget::make_##x( __VA_ARGS__ ); _(Value, deserialise_mir_lvalue() ) _(Path, deserialise_path() ) - _(Intrinsic, m_in.read_string() ) + _(Intrinsic, { + m_in.read_string(), + deserialise_pathparams() + }) #undef _ default: throw ""; diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index b4e7c6a2..f2394d40 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -526,7 +526,8 @@ namespace { serialise_path(e); ), (Intrinsic, - m_out.write_string(e); + m_out.write_string(e.name); + serialise_pathparams(e.params); ) ) } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 66f484ed..f2295ee6 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -618,6 +618,7 @@ namespace { visit_path(e2, ::HIR::Visitor::PathContext::VALUE); ), (Intrinsic, + visit_path_params(e2.params); ) ) for(auto& arg : te.args) diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp index c97a2699..d1fdc503 100644 --- a/src/mir/dump.cpp +++ b/src/mir/dump.cpp @@ -206,7 +206,7 @@ namespace { m_os << e2; ), (Intrinsic, - m_os << "\"" << e2 << "\""; + m_os << "\"" << e2.name << "\"::" << e2.params; ) ) m_os << "( "; diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 75ff1619..258449ef 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -1385,11 +1385,31 @@ namespace { auto next_block = m_builder.new_bb_unlinked(); auto res = m_builder.new_temporary( node.m_res_type ); - m_builder.end_block(::MIR::Terminator::make_Call({ - next_block, panic_block, - res.clone(), node.m_path.clone(), - mv$(values) - })); + // Emit intrinsics as a special call type + // TODO: Should the parameters be stored? (trans has get_lvalue_type, so no 100% needed) + if( node.m_path.m_data.is_Generic() ) + { + const auto& gpath = node.m_path.m_data.as_Generic(); + const auto& fcn = m_builder.crate().get_function_by_path(node.span(), gpath.m_path); + if( fcn.m_abi == "rust-intrinsic" ) + { + m_builder.end_block(::MIR::Terminator::make_Call({ + next_block, panic_block, + res.clone(), ::MIR::CallTarget::make_Intrinsic({ gpath.m_path.m_components.back(), gpath.m_params.clone() }), + mv$(values) + })); + } + } + + // If the call wasn't to an intrinsic, emit it as a path + if( m_builder.block_active() ) + { + m_builder.end_block(::MIR::Terminator::make_Call({ + next_block, panic_block, + res.clone(), node.m_path.clone(), + mv$(values) + })); + } m_builder.set_cur_block(panic_block); // TODO: Proper panic handling, including scope destruction diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp index 95ad81b3..2dd911ec 100644 --- a/src/mir/mir.cpp +++ b/src/mir/mir.cpp @@ -171,7 +171,7 @@ namespace MIR { os << e2; ), (Intrinsic, - os << "\"" << e2 << "\""; + os << "\"" << e2.name << "\"::" << e2.params; ) ) os << "( "; diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp index 4f4d70b0..1ac8ff78 100644 --- a/src/mir/mir.hpp +++ b/src/mir/mir.hpp @@ -164,7 +164,10 @@ extern ::std::ostream& operator<<(::std::ostream& os, const RValue& x); TAGGED_UNION(CallTarget, Intrinsic, (Value, LValue), (Path, ::HIR::Path), - (Intrinsic, ::std::string) + (Intrinsic, struct { + ::std::string name; + ::HIR::PathParams params; + }) ); TAGGED_UNION(Terminator, Incomplete, diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 9e29d7bf..a8fe0b0b 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -41,6 +41,7 @@ namespace { << "#include <stddef.h>\n" << "#include <stdint.h>\n" << "#include <stdbool.h>\n" + << "#include <string.h>\n" << "typedef uint32_t CHAR;\n" << "typedef struct { } tUNIT;\n" << "typedef struct { } tBANG;\n" @@ -263,6 +264,7 @@ namespace { void emit_function_ext(const ::HIR::Path& p, const ::HIR::Function& item, const Trans_Params& params) override { + m_of << "// extern \"" << item.m_abi << "\" " << p << "\n"; m_of << "extern "; emit_function_header(p, item, params); m_of << ";\n"; @@ -576,6 +578,7 @@ namespace { } mir_res.set_cur_stmt_term(i); + DEBUG("- " << code->blocks[i].terminator); TU_MATCHA( (code->blocks[i].terminator), (e), (Incomplete, m_of << "\tfor(;;);\n"; @@ -603,6 +606,138 @@ namespace { ), (Call, m_of << "\t"; + if( e.fcn.is_Intrinsic() ) + { + const auto& name = e.fcn.as_Intrinsic().name; + const auto& params = e.fcn.as_Intrinsic().params; + + struct H { + static const char* get_atomic_ordering(const ::MIR::TypeResolve& mir_res, const ::std::string& name, size_t prefix_len) { + if( name.size() < prefix_len ) + return "memory_order_seq_cst"; + const char* suffix = name.c_str() + prefix_len; + if( ::std::strcmp(suffix, "acq") == 0 ) { + return "memory_order_acquire"; + } + else if( ::std::strcmp(suffix, "rel") == 0 ) { + return "memory_order_release"; + } + else if( ::std::strcmp(suffix, "relaxed") == 0 ) { + return "memory_order_relaxed"; + } + else if( ::std::strcmp(suffix, "acqrel") == 0 ) { + return "memory_order_acq_rel"; + } + else { + MIR_BUG(mir_res, "Unknown atomic ordering suffix - '" << suffix << "'"); + } + } + }; + auto emit_atomic_cxchg = [&](const auto& e, const char* o_succ, const char* o_fail) { + emit_lvalue(e.ret_val); m_of << " = atomic_compare_exchange_strong_explicit("; + emit_lvalue(e.args.at(0)); + m_of << ", &"; emit_lvalue(e.args.at(1)); + m_of << ", "; emit_lvalue(e.args.at(2)); + m_of << ", "<<o_succ<<", "<<o_fail<<")"; + }; + if( name == "size_of" ) { + emit_lvalue(e.ret_val); m_of << " = sizeof("; emit_ctype(params.m_types.at(0)); m_of << ")"; + } + else if( name == "min_align_of" ) { + //emit_lvalue(e.ret_val); m_of << " = alignof("; emit_ctype(params.m_types.at(0)); m_of << ")"; + emit_lvalue(e.ret_val); m_of << " = __alignof__("; emit_ctype(params.m_types.at(0)); m_of << ")"; + } + else if( name == "transmute" ) { + m_of << "memcpy( &"; emit_lvalue(e.ret_val); m_of << ", &"; emit_lvalue(e.args.at(0)); m_of << ", sizeof("; emit_ctype(params.m_types.at(0)); m_of << "))"; + } + else if( name == "copy_nonoverlapping" ) { + m_of << "memcpy( "; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", "; emit_lvalue(e.args.at(2)); m_of << ")"; + } + else if( name == "forget" ) { + // Nothing needs to be done, this just stops the destructor from running. + } + else if( name == "uninit" ) { + // Do nothing, leaves the destination undefined + } + else if( name == "init" ) { + m_of << "memset( &"; emit_lvalue(e.ret_val); m_of << ", 0, sizeof("; emit_ctype(params.m_types.at(0)); m_of << "))"; + } + else if( name == "move_val_init" ) { + m_of << "*"; emit_lvalue(e.args.at(0)); m_of << " = "; emit_lvalue(e.args.at(1)); + } + else if( name == "abort" ) { + m_of << "abort()"; + } + // Overflowing Arithmatic + // HACK: Uses GCC intrinsics + else if( name == "add_with_overflow" ) { + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_add_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; + } + else if( name == "sub_with_overflow" ) { + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_sub_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; + } + else if( name == "mul_with_overflow" ) { + emit_lvalue(e.ret_val); m_of << "._1 = __builtin_mul_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << "._0)"; + } + else if( name == "overflowing_add" ) { + m_of << "__builtin_add_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; + } + else if( name == "overflowing_sub" ) { + m_of << "__builtin_sub_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; + } + else if( name == "overflowing_mul" ) { + m_of << "__builtin_mul_overflow("; emit_lvalue(e.args.at(0)); + m_of << ", "; emit_lvalue(e.args.at(1)); + m_of << ", &"; emit_lvalue(e.ret_val); m_of << ")"; + } + // --- Atomics! + // > Single-ordering atomics + else if( name == "atomic_xadd" || name.compare(0, 7+4+1, "atomic_xadd_") == 0 ) { + auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1); + emit_lvalue(e.ret_val); m_of << " = atomic_fetch_add_explicit("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", " << ordering << ")"; + } + else if( name == "atomic_load" || name.compare(0, 7+4+1, "atomic_load_") == 0 ) { + auto ordering = H::get_atomic_ordering(mir_res, name, 7+4+1); + emit_lvalue(e.ret_val); m_of << " = atomic_load_explicit("; emit_lvalue(e.args.at(0)); m_of << ", " << ordering << ")"; + } + else if( name == "atomic_store" || name.compare(0, 7+5+1, "atomic_store_") == 0 ) { + auto ordering = H::get_atomic_ordering(mir_res, name, 7+5+1); + m_of << "atomic_store_explicit("; emit_lvalue(e.args.at(0)); m_of << ", "; emit_lvalue(e.args.at(1)); m_of << ", " << ordering << ")"; + } + // Comare+Exchange (has two orderings) + else if( name == "atomic_cxchg_acq_failrelaxed" ) { + emit_atomic_cxchg(e, "memory_order_acquire", "memory_order_relaxed"); + } + else if( name == "atomic_cxchg_acqrel_failrelaxed" ) { + emit_atomic_cxchg(e, "memory_order_acq_rel", "memory_order_relaxed"); + } + else if( name.compare(0, 7+6+4, "atomic_cxchg_fail") == 0 ) { + auto fail_ordering = H::get_atomic_ordering(mir_res, name, 7+6+4); + emit_atomic_cxchg(e, "memory_order_seq_cst", fail_ordering); + } + else if( name == "atomic_cxchg" || name.compare(0, 7+6, "atomic_cxchg_") == 0 ) { + auto ordering = H::get_atomic_ordering(mir_res, name, 7+6); + emit_atomic_cxchg(e, ordering, ordering); + + } + else { + MIR_BUG(mir_res, "Unknown intrinsic '" << name << "'"); + } + m_of << ";\n"; + m_of << "\tgoto bb" << e.ret_block << ";\n"; + break ; + } + TU_MATCHA( (e.fcn), (e2), (Value, { @@ -809,7 +944,7 @@ namespace { m_of << "struct e_" << Trans_Mangle(te.path); ), (Unbound, - BUG(Span(), "Unbound path in trans - " << ty); + BUG(Span(), "Unbound type path in trans - " << ty); ), (Opaque, BUG(Span(), "Opaque path in trans - " << ty); diff --git a/src/trans/monomorphise.cpp b/src/trans/monomorphise.cpp index 24bf34d1..d129eae9 100644 --- a/src/trans/monomorphise.cpp +++ b/src/trans/monomorphise.cpp @@ -91,6 +91,7 @@ namespace { if( stmt.is_Drop() ) { const auto& e = stmt.as_Drop(); + DEBUG("- DROP " << e.slot); statements.push_back( ::MIR::Statement::make_Drop({ e.kind, monomorph_LValue(crate, params, e.slot) @@ -99,6 +100,7 @@ namespace { else { const auto& e = stmt.as_Assign(); + DEBUG("- " << e.dst << " = " << e.src); ::MIR::RValue rval; TU_MATCHA( (e.src), (se), @@ -221,6 +223,7 @@ namespace { ::MIR::Terminator terminator; + DEBUG("> " << block.terminator); TU_MATCHA( (block.terminator), (e), (Incomplete, //BUG(sp, "Incomplete block"); @@ -261,7 +264,7 @@ namespace { return params.monomorph(crate, e); ), (Intrinsic, - return e; + return ::MIR::CallTarget::make_Intrinsic({ e.name, params.monomorph(crate, e.params) }); ) ) throw ""; diff --git a/src/trans/trans_list.cpp b/src/trans/trans_list.cpp index 38e80468..f6a14c7e 100644 --- a/src/trans/trans_list.cpp +++ b/src/trans/trans_list.cpp @@ -78,9 +78,14 @@ t_cb_generic Trans_Params::get_cb() const ::HIR::GenericPath Trans_Params::monomorph(const ::HIR::Crate& crate, const ::HIR::GenericPath& p) const { - auto rv = monomorphise_genericpath_with(sp, p, this->get_cb(), false); + return ::HIR::GenericPath( p.m_path, this->monomorph(crate, p.m_params) ); +} + +::HIR::PathParams Trans_Params::monomorph(const ::HIR::Crate& crate, const ::HIR::PathParams& p) const +{ + auto rv = monomorphise_path_params_with(sp, p, this->get_cb(), false); ::StaticTraitResolve resolve { crate }; - for(auto& arg : rv.m_params.m_types) + for(auto& arg : rv.m_types) resolve.expand_associated_types(sp, arg); return rv; } diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 1297d2c2..bca75dac 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -33,6 +33,7 @@ struct Trans_Params ::HIR::TypeRef monomorph(const ::HIR::Crate& crate, const ::HIR::TypeRef& p) const; ::HIR::Path monomorph(const ::HIR::Crate& crate, const ::HIR::Path& p) const; ::HIR::GenericPath monomorph(const ::HIR::Crate& crate, const ::HIR::GenericPath& p) const; + ::HIR::PathParams monomorph(const ::HIR::Crate& crate, const ::HIR::PathParams& p) const; bool has_types() const { return pp_method.m_types.size() > 0 || pp_impl.m_types.size() > 0; |