[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