summaryrefslogtreecommitdiff
path: root/src/trans/codegen_c.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-02-03 21:10:09 +0800
committerJohn Hodge <tpg@mutabah.net>2017-02-03 21:10:09 +0800
commit9b8cdb083860f58bfd1cae6f05834bcc1b4f5ea5 (patch)
tree9821d21081f8adfdb26bf9f17d5ce96ba02cfcba /src/trans/codegen_c.cpp
parentdd91f16e461c04bd4528c79f2ab5d96f8ac759e1 (diff)
downloadmrust-9b8cdb083860f58bfd1cae6f05834bcc1b4f5ea5.tar.gz
Codegen C - Fix ctz/clz intrinsics
Diffstat (limited to 'src/trans/codegen_c.cpp')
-rw-r--r--src/trans/codegen_c.cpp49
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" ) {