diff options
author | John Hodge <tpg@mutabah.net> | 2017-02-03 21:10:09 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2017-02-03 21:10:09 +0800 |
commit | 9b8cdb083860f58bfd1cae6f05834bcc1b4f5ea5 (patch) | |
tree | 9821d21081f8adfdb26bf9f17d5ce96ba02cfcba /src | |
parent | dd91f16e461c04bd4528c79f2ab5d96f8ac759e1 (diff) | |
download | mrust-9b8cdb083860f58bfd1cae6f05834bcc1b4f5ea5.tar.gz |
Codegen C - Fix ctz/clz intrinsics
Diffstat (limited to 'src')
-rw-r--r-- | src/trans/codegen_c.cpp | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 73f068a3..5992d03d 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -80,11 +80,23 @@ namespace { << "static inline TRAITOBJ_PTR make_traitobjptr(void* ptr, void* vt) { TRAITOBJ_PTR rv = { ptr, vt }; return rv; }\n" << "\n" << "static inline size_t max(size_t a, size_t b) { return a < b ? b : a; }\n" + << "static inline uint64_t __builtin_clz64(uint64_t v) {\n" + << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n" + << "}\n" + << "static inline uint64_t __builtin_ctz64(uint64_t v) {\n" + << "\treturn (v&0xFFFFFFFF == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n" + << "}\n" << "static inline unsigned __int128 __builtin_bswap128(unsigned __int128 v) {\n" << "\tuint64_t lo = __builtin_bswap64((uint64_t)v);\n" << "\tuint64_t hi = __builtin_bswap64((uint64_t)(v>>64));\n" << "\treturn ((unsigned __int128)lo << 64) | (unsigned __int128)hi;\n" << "}\n" + << "static inline unsigned __int128 __builtin_clz128(unsigned __int128 v) {\n" + << "\treturn (v >> 64 != 0 ? __builtin_clz64(v>>64) : 64 + __builtin_clz64(v));\n" + << "}\n" + << "static inline unsigned __int128 __builtin_ctz128(unsigned __int128 v) {\n" + << "\treturn (v&0xFFFFFFFFFFFFFFFF == 0 ? __builtin_ctz64(v>>64) + 64 : __builtin_ctz64(v));\n" + << "}\n" << "\n" ; } @@ -2292,12 +2304,39 @@ namespace { } // Bit Twiddling // - CounT Leading Zeroes - else if( name == "ctlz" ) { - emit_lvalue(e.ret_val); m_of << " = __builtin_clz("; emit_lvalue(e.args.at(0)); m_of << ")"; - } // - CounT Trailing Zeroes - else if( name == "cttz" ) { - emit_lvalue(e.ret_val); m_of << " = __builtin_ctz("; emit_lvalue(e.args.at(0)); m_of << ")"; + else if( name == "ctlz" || name == "cttz" ) { + auto emit_arg0 = [&](){ emit_lvalue(e.args.at(0)); }; + const auto& ty = params.m_types.at(0); + emit_lvalue(e.ret_val); m_of << " = ("; emit_lvalue(e.args.at(0)); m_of << " != 0 ? "; + if( ty == ::HIR::CoreType::U128 ) + { + if( name == "ctlz" ) { + m_of << "__builtin_clz128("; emit_lvalue(e.args.at(0)); m_of << ")"; + } + else { + m_of << "__builtin_ctz128("; emit_lvalue(e.args.at(0)); m_of << ")"; + } + } + else if( ty == ::HIR::CoreType::U64 || (ty == ::HIR::CoreType::Usize /*&& target_is_64_bit */) ) + { + if( name == "ctlz" ) { + m_of << "__builtin_clz64("; emit_arg0(); m_of << ")"; + } + else { + m_of << "__builtin_ctz64("; emit_arg0(); m_of << ")"; + } + } + else + { + if( name == "ctlz" ) { + m_of << "__builtin_clz("; emit_lvalue(e.args.at(0)); m_of << ")"; + } + else { + m_of << "__builtin_ctz("; emit_lvalue(e.args.at(0)); m_of << ")"; + } + } + m_of << " : sizeof("; emit_ctype(ty); m_of << ")*8)"; } // - CounT POPulated else if( name == "ctpop" ) { |