summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-03-22 00:47:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-03-22 00:47:05 +0000
commitb30d11194ca3b430539c01674a35d4fbb8faa70d (patch)
treede2c5401e77c6156a66e3d9bbe33e0f81a7cd02c
parent584ce2f349e2f8f350826c88a21485132bafb8a4 (diff)
downloadbcm5719-llvm-b30d11194ca3b430539c01674a35d4fbb8faa70d.tar.gz
bcm5719-llvm-b30d11194ca3b430539c01674a35d4fbb8faa70d.zip
ubsan: Pass floating-point arguments to the runtime by value if they fit the
value argument. llvm-svn: 177689
-rw-r--r--compiler-rt/lib/ubsan/ubsan_value.cc36
-rw-r--r--compiler-rt/lib/ubsan/ubsan_value.h11
2 files changed, 38 insertions, 9 deletions
diff --git a/compiler-rt/lib/ubsan/ubsan_value.cc b/compiler-rt/lib/ubsan/ubsan_value.cc
index f17c58989db..5d77350d0c4 100644
--- a/compiler-rt/lib/ubsan/ubsan_value.cc
+++ b/compiler-rt/lib/ubsan/ubsan_value.cc
@@ -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");
}
diff --git a/compiler-rt/lib/ubsan/ubsan_value.h b/compiler-rt/lib/ubsan/ubsan_value.h
index e673f7af1d8..54ed5ad1931 100644
--- a/compiler-rt/lib/ubsan/ubsan_value.h
+++ b/compiler-rt/lib/ubsan/ubsan_value.h
@@ -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) {}
OpenPOWER on IntegriCloud