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; | 
