ubsan: Pass floating-point arguments to the runtime by value if they fit the
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 22 Mar 2013 00:47:05 +0000 (00:47 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 22 Mar 2013 00:47:05 +0000 (00:47 +0000)
value argument.

llvm-svn: 177689

compiler-rt/lib/ubsan/ubsan_value.cc
compiler-rt/lib/ubsan/ubsan_value.h

index f17c589..5d77350 100644 (file)
@@ -13,6 +13,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "ubsan_value.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
 
 using namespace __ubsan;
 
@@ -66,16 +68,34 @@ UIntMax Value::getPositiveIntValue() const {
 /// them to be passed in floating-point registers, so this has little cost).
 FloatMax Value::getFloatValue() const {
   CHECK(getType().isFloatTy());
-  switch (getType().getFloatBitWidth()) {
+  if (isInlineFloat()) {
+    switch (getType().getFloatBitWidth()) {
 #if 0
-  // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
-  //        from this to 'long double'.
-  case 16: return *reinterpret_cast<__fp16*>(Val);
+      // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
+      //        from '__fp16' to 'long double'.
+      case 16: {
+        __fp16 Value;
+        internal_memcpy(&Value, &Val, 4);
+        return Value;
+      }
 #endif
-  case 32: return *reinterpret_cast<float*>(Val);
-  case 64: return *reinterpret_cast<double*>(Val);
-  case 80: return *reinterpret_cast<long double*>(Val);
-  case 128: return *reinterpret_cast<long double*>(Val);
+      case 32: {
+        float Value;
+        internal_memcpy(&Value, &Val, 4);
+        return Value;
+      }
+      case 64: {
+        double Value;
+        internal_memcpy(&Value, &Val, 8);
+        return Value;
+      }
+    }
+  } else {
+    switch (getType().getFloatBitWidth()) {
+    case 64: return *reinterpret_cast<double*>(Val);
+    case 80: return *reinterpret_cast<long double*>(Val);
+    case 128: return *reinterpret_cast<long double*>(Val);
+    }
   }
   UNREACHABLE("unexpected floating point bit width");
 }
index e673f7a..54ed5ad 100644 (file)
@@ -108,7 +108,8 @@ public:
     /// integer otherwise.
     TK_Integer = 0x0000,
     /// A floating-point type. Low 16 bits are bit width. The value
-    /// representation is a pointer to the floating-point value.
+    /// representation is that of bitcasting the floating-point value to an
+    /// integer type.
     TK_Float = 0x0001,
     /// Any other type. The value representation is unspecified.
     TK_Unknown = 0xffff
@@ -162,6 +163,14 @@ class Value {
     return Bits <= InlineBits;
   }
 
+  /// Is \c Val a (zero-extended) integer representation of a float?
+  bool isInlineFloat() const {
+    CHECK(getType().isFloatTy());
+    const unsigned InlineBits = sizeof(ValueHandle) * 8;
+    const unsigned Bits = getType().getFloatBitWidth();
+    return Bits <= InlineBits;
+  }
+
 public:
   Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}