[llvm-commits] [compiler-rt] r165844 - in /compiler-rt/trunk/lib/ubsan: lit_tests/Float/ lit_tests/Float/cast-overflow.cpp ubsan_diag.cc ubsan_diag.h ubsan_handlers.cc ubsan_handlers.h ubsan_value.cc ubsan_value.h

Richard Smith richard-llvm at metafoo.co.uk
Fri Oct 12 15:57:15 PDT 2012


Author: rsmith
Date: Fri Oct 12 17:57:15 2012
New Revision: 165844

URL: http://llvm.org/viewvc/llvm-project?rev=165844&view=rev
Log:
-fcatch-undefined-behavior: Runtime library support for trapping conversions to or
from a floating-point type where the source value is not in the range of
representable values of the destination type.

Added:
    compiler-rt/trunk/lib/ubsan/lit_tests/Float/
    compiler-rt/trunk/lib/ubsan/lit_tests/Float/cast-overflow.cpp
Modified:
    compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
    compiler-rt/trunk/lib/ubsan/ubsan_diag.h
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
    compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
    compiler-rt/trunk/lib/ubsan/ubsan_value.cc
    compiler-rt/trunk/lib/ubsan/ubsan_value.h

Added: compiler-rt/trunk/lib/ubsan/lit_tests/Float/cast-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Float/cast-overflow.cpp?rev=165844&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Float/cast-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Float/cast-overflow.cpp Fri Oct 12 17:57:15 2012
@@ -0,0 +1,90 @@
+// RUN: %clang -fcatch-undefined-behavior %s -o %t
+// RUN: %t _
+// RUN: %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
+// RUN: %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
+// RUN: %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
+// RUN: %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
+// RUN: %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
+// RUN: %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
+// RUN: %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
+// FIXME: %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
+// RUN: %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
+// RUN: %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9
+
+// This test assumes float and double are IEEE-754 single- and double-precision.
+
+#include <stdint.h>
+#include <string.h>
+
+float Inf;
+float NaN;
+
+int main(int argc, char **argv) {
+  float MaxFloatRepresentableAsInt = 0x7fffff80;
+  (int)MaxFloatRepresentableAsInt; // ok
+  (int)-MaxFloatRepresentableAsInt; // ok
+
+  float MinFloatRepresentableAsInt = -0x7fffffff - 1;
+  (int)MinFloatRepresentableAsInt; // ok
+
+  float MaxFloatRepresentableAsUInt = 0xffffff00u;
+  (unsigned int)MaxFloatRepresentableAsUInt; // ok
+
+  unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);
+  (void)(float)FloatMaxAsUInt128; // ok
+
+  // Build a '+Inf'.
+  char InfVal[] = { 0x00, 0x00, 0x80, 0x7f };
+  float Inf;
+  memcpy(&Inf, InfVal, 4);
+
+  // Build a 'NaN'.
+  char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f };
+  float NaN;
+  memcpy(&NaN, NaNVal, 4);
+
+  switch (argv[1][0]) {
+    // FIXME: Produce a source location for these checks and test for it here.
+
+    // Floating point -> integer overflow.
+  case '0':
+    // Note that values between 0x7ffffe00 and 0x80000000 may or may not
+    // successfully round-trip, depending on the rounding mode.
+    // CHECK-0: fatal error: value 2.14748{{.*}} is outside the range of representable values of type 'int'
+    return MaxFloatRepresentableAsInt + 0x80;
+  case '1':
+    // CHECK-1: fatal error: value -2.14748{{.*}} is outside the range of representable values of type 'int'
+    return MinFloatRepresentableAsInt - 0x100;
+  case '2':
+    // CHECK-2: fatal error: value -0.001 is outside the range of representable values of type 'unsigned int'
+    return (unsigned)-0.001;
+  case '3':
+    // CHECK-3: fatal error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'
+    return (unsigned)(MaxFloatRepresentableAsUInt + 0x100);
+
+  case '4':
+    // CHECK-4: fatal error: value {{.*}} is outside the range of representable values of type 'int'
+    return Inf;
+  case '5':
+    // CHECK-5: fatal error: value {{.*}} is outside the range of representable values of type 'int'
+    return NaN;
+
+    // Integer -> floating point overflow.
+  case '6':
+    // CHECK-6: fatal error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'
+    return (float)(FloatMaxAsUInt128 + 1);
+  // FIXME: The backend cannot lower __fp16 operations on x86 yet.
+  //case '7':
+  //  (__fp16)65504; // ok
+  //  // CHECK-7: fatal error: value 65505 is outside the range of representable values of type '__fp16'
+  //  return (__fp16)65505;
+
+    // Floating point -> floating point overflow.
+  case '8':
+    // CHECK-8: fatal error: value 1e+39 is outside the range of representable values of type 'float'
+    return (float)1e39;
+  case '9':
+    // CHECK-9: fatal error: value {{.*}} is outside the range of representable values of type 'double'
+    return (double)Inf;
+  }
+}

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Fri Oct 12 17:57:15 2012
@@ -27,6 +27,8 @@
     AddArg(V.getSIntValue());
   else if (V.getType().isUnsignedIntegerTy())
     AddArg(V.getUIntValue());
+  else if (V.getType().isFloatTy())
+    AddArg(V.getFloatValue());
   else
     AddArg("<unknown>");
   return *this;
@@ -84,6 +86,9 @@
         else
           PrintHex(A.UInt);
         break;
+      case AK_Float:
+        fprintf(stderr, "%Lg", (long double)A.Float);
+        break;
       case AK_Pointer:
         fprintf(stderr, "0x%zx", (uptr)A.Pointer);
         break;

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Fri Oct 12 17:57:15 2012
@@ -35,6 +35,7 @@
     AK_String, ///< A string argument, displayed as-is.
     AK_UInt,   ///< An unsigned integer argument.
     AK_SInt,   ///< A signed integer argument.
+    AK_Float,  ///< A floating-point argument.
     AK_Pointer ///< A pointer argument, displayed in hexadecimal.
   };
 
@@ -44,6 +45,7 @@
     Arg(const char *String) : Kind(AK_String), String(String) {}
     Arg(UIntMax UInt) : Kind(AK_UInt), UInt(UInt) {}
     Arg(SIntMax SInt) : Kind(AK_SInt), SInt(SInt) {}
+    Arg(FloatMax Float) : Kind(AK_Float), Float(Float) {}
     Arg(const void *Pointer) : Kind(AK_Pointer), Pointer(Pointer) {}
 
     ArgKind Kind;
@@ -51,6 +53,7 @@
       const char *String;
       UIntMax UInt;
       SIntMax SInt;
+      FloatMax Float;
       const void *Pointer;
     };
   };

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc Fri Oct 12 17:57:15 2012
@@ -134,3 +134,11 @@
     << Value(Data->Type, Bound);
   Die();
 }
+
+void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
+                                                 ValueHandle From) {
+  Diag(SourceLocation(), "value %0 is outside the range of representable "
+                         "values of type %2")
+    << Value(Data->FromType, From) << Data->FromType << Data->ToType;
+  Die();
+}

Modified: compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.h?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.h Fri Oct 12 17:57:15 2012
@@ -85,6 +85,16 @@
 extern "C" void __ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
                                                       ValueHandle Bound);
 
+struct FloatCastOverflowData {
+  // FIXME: SourceLocation Loc;
+  const TypeDescriptor &FromType;
+  const TypeDescriptor &ToType;
+};
+
+/// \brief Handle overflow in a conversion to or from a floating-point type.
+extern "C" void __ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data,
+                                                   ValueHandle From);
+
 }
 
 #endif // UBSAN_HANDLERS_H

Modified: compiler-rt/trunk/lib/ubsan/ubsan_value.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_value.cc?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.cc Fri Oct 12 17:57:15 2012
@@ -58,7 +58,7 @@
 /// Get the floating-point value of this object, extended to a long double.
 /// These are always passed by address (our calling convention doesn't allow
 /// them to be passed in floating-point registers, so this has little cost).
-long double Value::getFloatValue() const {
+FloatMax Value::getFloatValue() const {
   CHECK(getType().isFloatTy());
   switch (getType().getFloatBitWidth()) {
 #if 0

Modified: compiler-rt/trunk/lib/ubsan/ubsan_value.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_value.h?rev=165844&r1=165843&r2=165844&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.h (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.h Fri Oct 12 17:57:15 2012
@@ -39,6 +39,9 @@
 typedef u64 UIntMax;
 #endif
 
+/// \brief Largest floating-point type we support.
+typedef long double FloatMax;
+
 
 /// \brief A description of a source location. This corresponds to Clang's
 /// \c PresumedLoc type.
@@ -48,6 +51,7 @@
   u32 Column;
 
 public:
+  SourceLocation() : Filename(), Line(), Column() {}
   SourceLocation(const char *Filename, unsigned Line, unsigned Column)
     : Filename(Filename), Line(Line), Column(Column) {}
 
@@ -164,7 +168,7 @@
   }
 
   /// \brief Get this value as a floating-point quantity.
-  long double getFloatValue() const;
+  FloatMax getFloatValue() const;
 };
 
 } // namespace __ubsan





More information about the llvm-commits mailing list