Disabling conversion with contained value for Optional
[folly.git] / folly / Bits.cpp
index 41c2bc46ea32a6e5f18fae01e0d41beb9cf13c87..62b759f09182193e78ca79a57babff82dbc4c6d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2013 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 // popcnt
 #ifndef __POPCNT__
 
-namespace {
+// Clang doesn't support ifuncs. This also allows ifunc support to be explicitly
+// passed in as a compile flag.
+#ifndef FOLLY_HAVE_IFUNC
+#  ifdef __clang__
+#    define FOLLY_HAVE_IFUNC 0
+#  else
+#    define FOLLY_HAVE_IFUNC 1
+#  endif
+#endif
 
-int popcount_inst(unsigned int x) {
-  asm ("popcntl %0, %0" : "=r" (x) : "0" (x));
-  return x;
-}
+namespace {
 
 int popcount_builtin(unsigned int x) {
   return __builtin_popcount(x);
 }
 
-int popcountll_inst(unsigned long long x) {
-  asm ("popcntq %0, %0" : "=r" (x) : "0" (x));
-  return x;
-}
-
 int popcountll_builtin(unsigned long long x) {
   return __builtin_popcountll(x);
 }
 
+
+#if FOLLY_HAVE_IFUNC
+
+// Strictly speaking, these versions of popcount are usable without ifunc
+// support. However, we would have to check, via CpuId, if the processor
+// implements the popcnt instruction first, which is what we use ifunc for.
+int popcount_inst(unsigned int x) {
+  int n;
+  asm ("popcntl %1, %0" : "=r" (n) : "r" (x));
+  return n;
+}
+
+int popcountll_inst(unsigned long long x) {
+  unsigned long long n;
+  asm ("popcntq %1, %0" : "=r" (n) : "r" (x));
+  return n;
+}
+
 typedef decltype(popcount_builtin) Type_popcount;
 typedef decltype(popcountll_builtin) Type_popcountll;
 
-}  // namespace
-
 // This function is called on startup to resolve folly::detail::popcount
 extern "C" Type_popcount* folly_popcount_ifunc() {
   return folly::CpuId().popcnt() ?  popcount_inst : popcount_builtin;
@@ -57,18 +73,30 @@ extern "C" Type_popcountll* folly_popcountll_ifunc() {
   return folly::CpuId().popcnt() ?  popcountll_inst : popcountll_builtin;
 }
 
+#endif // FOLLY_HAVE_IFUNC
+
+}  // namespace
+
 namespace folly {
 namespace detail {
 
 // Call folly_popcount_ifunc on startup to resolve to either popcount_inst
 // or popcount_builtin
 int popcount(unsigned int x)
+#if FOLLY_HAVE_IFUNC
   __attribute__((ifunc("folly_popcount_ifunc")));
+#else
+{  return popcount_builtin(x); }
+#endif
 
 // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst
 // or popcountll_builtin
 int popcountll(unsigned long long x)
+#if FOLLY_HAVE_IFUNC
   __attribute__((ifunc("folly_popcountll_ifunc")));
+#else
+{  return popcountll_builtin(x); }
+#endif
 
 }  // namespace detail
 }  // namespace folly