diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-22 00:47:05 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-22 00:47:05 +0000 |
commit | ec7962d874159f02ad9b1657b627ceb53fea55ab (patch) | |
tree | d7fb8914202fe141b6139d31f79f77f7337ec570 /lib/ubsan | |
parent | 3f814987cee8310083cb4a5cfb1a3850f9a067a1 (diff) | |
download | compiler-rt-ec7962d874159f02ad9b1657b627ceb53fea55ab.tar.gz |
ubsan: Pass floating-point arguments to the runtime by value if they fit the
value argument.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177689 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/ubsan_value.cc | 36 | ||||
-rw-r--r-- | lib/ubsan/ubsan_value.h | 11 |
2 files changed, 38 insertions, 9 deletions
diff --git a/lib/ubsan/ubsan_value.cc b/lib/ubsan/ubsan_value.cc index f17c58989..5d77350d0 100644 --- a/lib/ubsan/ubsan_value.cc +++ b/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/lib/ubsan/ubsan_value.h b/lib/ubsan/ubsan_value.h index e673f7af1..54ed5ad19 100644 --- a/lib/ubsan/ubsan_value.h +++ b/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) {} |