[llvm-commits] [compiler-rt] r165533 - in /compiler-rt/trunk/lib: ./ ubsan/ ubsan/lit_tests/ ubsan/lit_tests/Integer/ ubsan/lit_tests/Misc/ ubsan/lit_tests/TypeCheck/
Richard Smith
richard-llvm at metafoo.co.uk
Tue Oct 9 12:34:33 PDT 2012
Author: rsmith
Date: Tue Oct 9 14:34:32 2012
New Revision: 165533
URL: http://llvm.org/viewvc/llvm-project?rev=165533&view=rev
Log:
Add a runtime diagnostics library for Clang's -fcatch-undefined-behavior.
Added:
compiler-rt/trunk/lib/ubsan/
compiler-rt/trunk/lib/ubsan/CMakeLists.txt
compiler-rt/trunk/lib/ubsan/lit_tests/
compiler-rt/trunk/lib/ubsan/lit_tests/CMakeLists.txt
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/add-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-zero.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/mul-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/negate-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/shift.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Integer/sub-overflow.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Misc/
compiler-rt/trunk/lib/ubsan/lit_tests/Misc/missing_return.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/Misc/unreachable.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/
compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/null.cpp
compiler-rt/trunk/lib/ubsan/lit_tests/lit.cfg
compiler-rt/trunk/lib/ubsan/lit_tests/lit.site.cfg.in
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
Modified:
compiler-rt/trunk/lib/CMakeLists.txt
Modified: compiler-rt/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/CMakeLists.txt?rev=165533&r1=165532&r2=165533&view=diff
==============================================================================
--- compiler-rt/trunk/lib/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/CMakeLists.txt Tue Oct 9 14:34:32 2012
@@ -10,6 +10,8 @@
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
# ThreadSanitizer is supported on Linux only.
add_subdirectory(tsan)
+ # UndefinedBehaviorSanitizer has been tested on Linux only.
+ add_subdirectory(ubsan)
endif()
# FIXME: Add support for the profile library.
Added: compiler-rt/trunk/lib/ubsan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/CMakeLists.txt?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/CMakeLists.txt (added)
+++ compiler-rt/trunk/lib/ubsan/CMakeLists.txt Tue Oct 9 14:34:32 2012
@@ -0,0 +1,35 @@
+# Build for the undefined behavior sanitizer runtime support library.
+
+set(UBSAN_SOURCES
+ ubsan_diag.cc
+ ubsan_handlers.cc
+ ubsan_value.cc
+ )
+
+include_directories(..)
+
+set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+
+set(UBSAN_RUNTIME_LIBRARIES)
+
+if(CAN_TARGET_X86_64)
+ add_library(clang_rt.ubsan-x86_64 STATIC ${UBSAN_SOURCES})
+ set_target_compile_flags(clang_rt.ubsan-x86_64
+ ${UBSAN_CFLAGS} ${TARGET_X86_64_CFLAGS}
+ )
+ list(APPEND UBSAN_RUNTIME_LIBRARIES clang_rt.ubsan-x86_64)
+endif()
+
+if(CAN_TARGET_I386)
+ add_library(clang_rt.ubsan-i386 STATIC ${UBSAN_SOURCES})
+ set_target_compile_flags(clang_rt.ubsan-i386
+ ${UBSAN_CFLAGS} ${TARGET_I386_CFLAGS}
+ )
+ list(APPEND UBSAN_RUNTIME_LIBRARIES clang_rt.ubsan-i386)
+endif()
+
+set_property(TARGET ${UBSAN_RUNTIME_LIBRARIES} APPEND PROPERTY
+ COMPILE_DEFINITIONS ${UBSAN_COMMON_DEFINITIONS})
+add_clang_compiler_rt_libraries(${UBSAN_RUNTIME_LIBRARIES})
+
+add_subdirectory(lit_tests)
Added: compiler-rt/trunk/lib/ubsan/lit_tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/CMakeLists.txt?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/CMakeLists.txt (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/CMakeLists.txt Tue Oct 9 14:34:32 2012
@@ -0,0 +1,22 @@
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+
+if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}")
+ # Run UBSan output tests only if we're not cross-compiling,
+ # and can be sure that clang would produce working binaries.
+ set(UBSAN_TEST_DEPS
+ clang clang-headers FileCheck count not
+ ${UBSAN_RUNTIME_LIBRARIES}
+ )
+ set(UBSAN_TEST_PARAMS
+ ubsan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+ add_lit_testsuite(check-ubsan "Running UndefinedBehaviorSanitizer tests"
+ ${CMAKE_CURRENT_BINARY_DIR}
+ PARAMS ${UBSAN_TEST_PARAMS}
+ DEPENDS ${UBSAN_TEST_DEPS}
+ )
+ set_target_properties(check-ubsan PROPERTIES FOLDER "UBSan unittests")
+endif()
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/add-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/add-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/add-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/add-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,27 @@
+// RUN: %clang -DADD_I32 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I32
+// RUN: %clang -DADD_I64 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I64
+// RUN: %clang -DADD_I128 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=ADD_I128
+
+#include <stdint.h>
+
+int main() {
+ // These promote to 'int'.
+ (void)(int8_t(0x7f) + int8_t(0x7f));
+ (void)(int16_t(0x3fff) + int16_t(0x4000));
+
+#ifdef ADD_I32
+ int32_t k = 0x12345678;
+ k += 0x789abcde;
+ // CHECK-ADD_I32: add-overflow.cpp:14:5: fatal error: signed integer overflow: 305419896 + 2023406814 cannot be represented in type 'int32_t' (aka 'int')
+#endif
+
+#ifdef ADD_I64
+ (void)(int64_t(8000000000000000000ll) + int64_t(2000000000000000000ll));
+ // CHECK-ADD_I64: 8000000000000000000 + 2000000000000000000 cannot be represented in type 'long'
+#endif
+
+#ifdef ADD_I128
+ (void)((__int128_t(1) << 126) + (__int128_t(1) << 126));
+ // CHECK-ADD_I128: 0x40000000000000000000000000000000 + 0x40000000000000000000000000000000 cannot be represented in type '__int128'
+#endif
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,10 @@
+// RUN: %clang -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+
+int main() {
+ unsigned(0x80000000) / -1;
+
+ // CHECK: div-overflow.cpp:9:23: fatal error: division of -2147483648 by -1 cannot be represented in type 'int'
+ int32_t(0x80000000) / -1;
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-zero.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-zero.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-zero.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/div-zero.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,9 @@
+// RUN: %clang -fcatch-undefined-behavior -DDIVIDEND=0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -fcatch-undefined-behavior -DDIVIDEND=1U %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -fcatch-undefined-behavior -DDIVIDEND=1.5 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -fcatch-undefined-behavior -DDIVIDEND='__int128(123)' %s -o %t && %t 2>&1 | FileCheck %s
+
+int main() {
+ // CHECK: div-zero.cpp:8:12: fatal error: division by zero
+ DIVIDEND / 0;
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/incdec-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,16 @@
+// RUN: %clang -DOP=n++ -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -DOP=++n -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -DOP=m-- -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clang -DOP=--m -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+
+int main() {
+ int n = 0x7ffffffd;
+ n++;
+ n++;
+ int m = -n - 1;
+ // CHECK: incdec-overflow.cpp:15:3: fatal error: signed integer overflow: [[MINUS:-?]]214748364
+ // CHECK: + [[MINUS]]1 cannot be represented in type 'int'
+ OP;
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/mul-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/mul-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/mul-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/mul-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,14 @@
+// RUN: %clang -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <stdint.h>
+
+int main() {
+ // These promote to 'int'.
+ (void)(int8_t(-2) * int8_t(0x7f));
+ (void)(int16_t(0x7fff) * int16_t(0x7fff));
+ (void)(uint16_t(0xffff) * int16_t(0x7fff));
+ (void)(uint16_t(0xffff) * uint16_t(0x8000));
+
+ // CHECK: mul-overflow.cpp:13:27: fatal error: signed integer overflow: 65535 * 32769 cannot be represented in type 'int'
+ (void)(uint16_t(0xffff) * uint16_t(0x8001));
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/negate-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/negate-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/negate-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/negate-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,7 @@
+// RUN: %clang -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s
+
+int main() {
+ -unsigned(-0x7fffffff - 1); // ok
+ // CHECK: negate-overflow.cpp:6:10: fatal error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
+ return -(-0x7fffffff - 1);
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/shift.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/shift.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/shift.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/shift.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,37 @@
+// RUN: %clang -DLSH_OVERFLOW -DOP='<<' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=LSH_OVERFLOW
+// RUN: %clang -DLSH_OVERFLOW -DOP='<<=' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=LSH_OVERFLOW
+// RUN: %clang -DTOO_LOW -DOP='<<' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW
+// RUN: %clang -DTOO_LOW -DOP='>>' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW
+// RUN: %clang -DTOO_LOW -DOP='<<=' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW
+// RUN: %clang -DTOO_LOW -DOP='>>=' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_LOW
+// RUN: %clang -DTOO_HIGH -DOP='<<' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH
+// RUN: %clang -DTOO_HIGH -DOP='>>' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH
+// RUN: %clang -DTOO_HIGH -DOP='<<=' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH
+// RUN: %clang -DTOO_HIGH -DOP='>>=' -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=TOO_HIGH
+
+#include <stdint.h>
+
+int main() {
+ int a = 1;
+ unsigned b = 1;
+
+ a <<= 31; // ok in C++11, not ok in C99/C11
+ b <<= 31; // ok
+ b <<= 1; // still ok, unsigned
+
+#ifdef LSH_OVERFLOW
+ // CHECK-LSH_OVERFLOW: shift.cpp:24:5: fatal error: left shift of negative value -2147483648
+ a OP 1;
+#endif
+
+#ifdef TOO_LOW
+ // CHECK-TOO_LOW: shift.cpp:29:5: fatal error: shift exponent -3 is negative
+ a OP (-3);
+#endif
+
+#ifdef TOO_HIGH
+ a = 0;
+ // CHECK-TOO_HIGH: shift.cpp:35:5: fatal error: shift exponent 32 is too large for 32-bit type 'int'
+ a OP 32;
+#endif
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Integer/sub-overflow.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Integer/sub-overflow.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Integer/sub-overflow.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Integer/sub-overflow.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,26 @@
+// RUN: %clang -DSUB_I32 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I32
+// RUN: %clang -DSUB_I64 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I64
+// RUN: %clang -DSUB_I128 -fcatch-undefined-behavior %s -o %t && %t 2>&1 | FileCheck %s --check-prefix=SUB_I128
+
+#include <stdint.h>
+
+int main() {
+ // These promote to 'int'.
+ (void)(int8_t(-2) - int8_t(0x7f));
+ (void)(int16_t(-2) - int16_t(0x7fff));
+
+#ifdef SUB_I32
+ (void)(int32_t(-2) - int32_t(0x7fffffff));
+ // CHECK-SUB_I32: sub-overflow.cpp:13:22: fatal error: signed integer overflow: -2 - 2147483647 cannot be represented in type 'int'
+#endif
+
+#ifdef SUB_I64
+ (void)(int64_t(-8000000000000000000ll) - int64_t(2000000000000000000ll));
+ // CHECK-SUB_I64: -8000000000000000000 - 2000000000000000000 cannot be represented in type 'long'
+#endif
+
+#ifdef SUB_I128
+ (void)(-(__int128_t(1) << 126) - (__int128_t(1) << 126) - 1);
+ // CHECK-SUB_I128: 0x80000000000000000000000000000000 - 1 cannot be represented in type '__int128'
+#endif
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Misc/missing_return.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Misc/missing_return.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Misc/missing_return.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Misc/missing_return.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,9 @@
+// RUN: %clang -fcatch-undefined-behavior %s -O3 -o %t && %t 2>&1 | FileCheck %s
+
+// CHECK: missing_return.cpp:4:5: fatal error: execution reached the end of a value-returning function without returning a value
+int f() {
+}
+
+int main(int, char **argv) {
+ return f();
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/Misc/unreachable.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/Misc/unreachable.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/Misc/unreachable.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/Misc/unreachable.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,6 @@
+// RUN: %clang -fcatch-undefined-behavior %s -O3 -o %t && %t 2>&1 | FileCheck %s
+
+int main(int, char **argv) {
+ // CHECK: unreachable.cpp:5:3: fatal error: execution reached a __builtin_unreachable() call
+ __builtin_unreachable();
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/misaligned.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,42 @@
+// RUN: %clang -fcatch-undefined-behavior %s -O3 -o %t
+// RUN: %t l0 && %t s0 && %t r0 && %t m0 && %t f0
+// RUN: %t l1 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
+// RUN: %t s1 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
+// RUN: %t r1 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
+// RUN: %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
+// RUN: %t f1 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
+
+struct S {
+ int f() { return 0; }
+ int k;
+};
+
+int main(int, char **argv) {
+ char c[5] __attribute__((aligned(4))) = {};
+
+ // Pointer value may be unspecified here, but behavior is not undefined.
+ int *p = (int*)&c[argv[1][1] - '0'];
+ S *s = (S*)p;
+
+ (void)*p; // ok!
+
+ switch (argv[1][0]) {
+ case 'l':
+ // CHECK-LOAD: misaligned.cpp:26:12: fatal error: load of misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ return *p;
+ case 's':
+ // CHECK-STORE: misaligned.cpp:29:5: fatal error: store to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ *p = 1;
+ break;
+ case 'r':
+ // CHECK-REFERENCE: misaligned.cpp:33:15: fatal error: reference binding to misaligned address 0x{{[0-9a-f]*}} for type 'int', which requires 4 byte alignment
+ {int &r = *p;}
+ break;
+ case 'm':
+ // CHECK-MEMBER: misaligned.cpp:37:15: fatal error: member access within misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
+ return s->k;
+ case 'f':
+ // CHECK-MEMFUN: misaligned.cpp:40:12: fatal error: member call on misaligned address 0x{{[0-9a-f]*}} for type 'S', which requires 4 byte alignment
+ return s->f();
+ }
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/null.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/null.cpp?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/null.cpp (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/TypeCheck/null.cpp Tue Oct 9 14:34:32 2012
@@ -0,0 +1,38 @@
+// RUN: %clang -fcatch-undefined-behavior %s -O3 -o %t
+// RUN: %t l 2>&1 | FileCheck %s --check-prefix=CHECK-LOAD
+// RUN: %t s 2>&1 | FileCheck %s --check-prefix=CHECK-STORE
+// RUN: %t r 2>&1 | FileCheck %s --check-prefix=CHECK-REFERENCE
+// RUN: %t m 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER
+// RUN: %t f 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN
+
+struct S {
+ int f() { return 0; }
+ int k;
+};
+
+int main(int, char **argv) {
+ int *p = 0;
+ S *s = 0;
+
+ (void)*p; // ok!
+
+ switch (argv[1][0]) {
+ case 'l':
+ // CHECK-LOAD: null.cpp:22:12: fatal error: load of null pointer of type 'int'
+ return *p;
+ case 's':
+ // CHECK-STORE: null.cpp:25:5: fatal error: store to null pointer of type 'int'
+ *p = 1;
+ break;
+ case 'r':
+ // CHECK-REFERENCE: null.cpp:29:15: fatal error: reference binding to null pointer of type 'int'
+ {int &r = *p;}
+ break;
+ case 'm':
+ // CHECK-MEMBER: null.cpp:33:15: fatal error: member access within null pointer of type 'S'
+ return s->k;
+ case 'f':
+ // CHECK-MEMFUN: null.cpp:36:12: fatal error: member call on null pointer of type 'S'
+ return s->f();
+ }
+}
Added: compiler-rt/trunk/lib/ubsan/lit_tests/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/lit.cfg?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/lit.cfg (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/lit.cfg Tue Oct 9 14:34:32 2012
@@ -0,0 +1,64 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'UndefinedBehaviorSanitizer'
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+def DisplayNoConfigMessage():
+ lit.fatal("No site specific configuration available! " +
+ "Try running your test from the build tree or running " +
+ "make check-ubsan")
+
+# Figure out LLVM source root.
+llvm_src_root = getattr(config, 'llvm_src_root', None)
+if llvm_src_root is None:
+ # We probably haven't loaded the site-specific configuration: the user
+ # is likely trying to run a test file directly, and the site configuration
+ # wasn't created by the build system or we're performing an out-of-tree build.
+ ubsan_site_cfg = lit.params.get('ubsan_site_config', None)
+ if ubsan_site_cfg and os.path.exists(ubsan_site_cfg):
+ lit.load_config(config, ubsan_site_cfg)
+ raise SystemExit
+
+ # Try to guess the location of site-specific configuration using llvm-config
+ # util that can point where the build tree is.
+ llvm_config = lit.util.which("llvm-config", config.environment["PATH"])
+ if not llvm_config:
+ DisplayNoConfigMessage()
+
+ # Validate that llvm-config points to the same source tree.
+ llvm_src_root = lit.util.capture(["llvm-config", "--src-root"]).strip()
+ ubsan_test_src_root = os.path.join(llvm_src_root, "projects", "compiler-rt",
+ "lib", "ubsan", "lit_tests")
+ if (os.path.realpath(ubsan_test_src_root) !=
+ os.path.realpath(config.test_source_root)):
+ DisplayNoConfigMessage()
+
+ # Find out the presumed location of generated site config.
+ llvm_obj_root = lit.util.capture(["llvm-config", "--obj-root"]).strip()
+ ubsan_site_cfg = os.path.join(llvm_obj_root, "projects", "compiler-rt",
+ "lib", "ubsan", "lit_tests", "lit.site.cfg")
+ if not ubsan_site_cfg or not os.path.exists(ubsan_site_cfg):
+ DisplayNoConfigMessage()
+
+ lit.load_config(config, ubsan_site_cfg)
+ raise SystemExit
+
+# Setup attributes common for all compiler-rt projects.
+compiler_rt_lit_cfg = os.path.join(llvm_src_root, "projects", "compiler-rt",
+ "lib", "lit.common.cfg")
+if not compiler_rt_lit_cfg or not os.path.exists(compiler_rt_lit_cfg):
+ lit.fatal("Can't find common compiler-rt lit config at: %r"
+ % compiler_rt_lit_cfg)
+lit.load_config(config, compiler_rt_lit_cfg)
+
+# Default test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp']
+
+# UndefinedBehaviorSanitizer tests are currently supported on Linux only.
+if config.host_os not in ['Linux']:
+ config.unsupported = True
Added: compiler-rt/trunk/lib/ubsan/lit_tests/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/lit_tests/lit.site.cfg.in?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/lit_tests/lit.site.cfg.in (added)
+++ compiler-rt/trunk/lib/ubsan/lit_tests/lit.site.cfg.in Tue Oct 9 14:34:32 2012
@@ -0,0 +1,19 @@
+## Autogenerated by LLVM/Clang configuration.
+# Do not edit!
+
+config.clang = "@LLVM_BINARY_DIR@/bin/clang"
+config.host_os = "@HOST_OS@"
+config.llvm_src_root = "@LLVM_SOURCE_DIR@"
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.target_triple = "@TARGET_TRIPLE@"
+
+# LLVM tools dir can be passed in lit parameters, so try to
+# apply substitution.
+try:
+ config.llvm_tools_dir = config.llvm_tools_dir % lit.params
+except KeyError,e:
+ key, = e.args
+ lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key, key))
+
+# Let the main config do the real work.
+lit.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
Added: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Tue Oct 9 14:34:32 2012
@@ -0,0 +1,97 @@
+//===-- ubsan_diag.cc -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostic reporting for the UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_diag.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+
+using namespace __ubsan;
+
+Diag &Diag::operator<<(const TypeDescriptor &V) {
+ return AddArg(V.getTypeName());
+}
+
+Diag &Diag::operator<<(const Value &V) {
+ if (V.getType().isSignedIntegerTy())
+ AddArg(V.getSIntValue());
+ else if (V.getType().isUnsignedIntegerTy())
+ AddArg(V.getUIntValue());
+ else
+ AddArg("<unknown>");
+ return *this;
+}
+
+/// Hexadecimal printing for numbers too large for fprintf to handle directly.
+static void PrintHex(UIntMax Val) {
+#ifdef HAVE_INT128_T
+ fprintf(stderr, "0x%08x%08x%08x%08x",
+ (unsigned int)(Val >> 96),
+ (unsigned int)(Val >> 64),
+ (unsigned int)(Val >> 32),
+ (unsigned int)(Val));
+#else
+ UNREACHABLE("long long smaller than 64 bits?");
+#endif
+}
+
+Diag::~Diag() {
+ // FIXME: This is non-portable.
+ bool UseAnsiColor = isatty(STDERR_FILENO);
+ if (UseAnsiColor)
+ fprintf(stderr, "\033[1m");
+ if (Loc.isInvalid())
+ fprintf(stderr, "<unknown>:");
+ else {
+ fprintf(stderr, "%s:%d:", Loc.getFilename(), Loc.getLine());
+ if (Loc.getColumn())
+ fprintf(stderr, "%d:", Loc.getColumn());
+ }
+ if (UseAnsiColor)
+ fprintf(stderr, "\033[31m");
+ fprintf(stderr, " fatal error: ");
+ if (UseAnsiColor)
+ fprintf(stderr, "\033[0;1m");
+ for (const char *Msg = Message; *Msg; ++Msg) {
+ if (*Msg != '%')
+ fputc((unsigned char)*Msg, stderr);
+ else {
+ const Arg &A = Args[*++Msg - '0'];
+ switch (A.Kind) {
+ case AK_String:
+ fprintf(stderr, "%s", A.String);
+ break;
+ case AK_SInt:
+ // 'long long' is guaranteed to be at least 64 bits wide.
+ if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX)
+ fprintf(stderr, "%lld", (long long)A.SInt);
+ else
+ PrintHex(A.SInt);
+ break;
+ case AK_UInt:
+ if (A.UInt <= UINT64_MAX)
+ fprintf(stderr, "%llu", (unsigned long long)A.UInt);
+ else
+ PrintHex(A.UInt);
+ break;
+ case AK_Pointer:
+ fprintf(stderr, "0x%zx", (uptr)A.Pointer);
+ break;
+ }
+ }
+ }
+ fputc('\n', stderr);
+ if (UseAnsiColor)
+ fprintf(stderr, "\033[0m");
+ fflush(stderr);
+}
Added: compiler-rt/trunk/lib/ubsan/ubsan_diag.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.h?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.h (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.h Tue Oct 9 14:34:32 2012
@@ -0,0 +1,88 @@
+//===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Diagnostics emission for Clang's undefined behavior sanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_DIAG_H
+#define UBSAN_DIAG_H
+
+#include "ubsan_value.h"
+
+namespace __ubsan {
+
+/// \brief Representation of an in-flight diagnostic.
+///
+/// Temporary \c Diag instances are created by the handler routines to
+/// accumulate arguments for a diagnostic. The destructor emits the diagnostic
+/// message.
+class Diag {
+ /// The source location at which the problem occurred.
+ const SourceLocation &Loc;
+
+ /// The message which will be emitted, with %0, %1, ... placeholders for
+ /// arguments.
+ const char *Message;
+
+ /// Kinds of arguments, corresponding to members of \c Arg's union.
+ enum ArgKind {
+ AK_String, ///< A string argument, displayed as-is.
+ AK_UInt, ///< An unsigned integer argument.
+ AK_SInt, ///< A signed integer argument.
+ AK_Pointer ///< A pointer argument, displayed in hexadecimal.
+ };
+
+ /// An individual diagnostic message argument.
+ struct Arg {
+ Arg() {}
+ 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(const void *Pointer) : Kind(AK_Pointer), Pointer(Pointer) {}
+
+ ArgKind Kind;
+ union {
+ const char *String;
+ UIntMax UInt;
+ SIntMax SInt;
+ const void *Pointer;
+ };
+ };
+
+ static const unsigned MaxArgs = 5;
+
+ /// The arguments which have been added to this diagnostic so far.
+ Arg Args[MaxArgs];
+ unsigned NumArgs;
+
+ Diag &AddArg(Arg A) {
+ CHECK(NumArgs != MaxArgs);
+ Args[NumArgs++] = A;
+ return *this;
+ }
+
+ /// \c Diag objects are not copyable.
+ Diag(const Diag &); // NOT IMPLEMENTED
+ Diag &operator=(const Diag &);
+
+public:
+ Diag(const SourceLocation &Loc, const char *Message)
+ : Loc(Loc), Message(Message), NumArgs(0) {}
+ ~Diag();
+
+ Diag &operator<<(const char *Str) { return AddArg(Str); }
+ Diag &operator<<(unsigned long long V) { return AddArg(UIntMax(V)); }
+ Diag &operator<<(const void *V) { return AddArg(V); }
+ Diag &operator<<(const TypeDescriptor &V);
+ Diag &operator<<(const Value &V);
+};
+
+} // namespace __ubsan
+
+#endif // UBSAN_DIAG_H
Added: compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.cc Tue Oct 9 14:34:32 2012
@@ -0,0 +1,128 @@
+//===-- ubsan_report.cc ---------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Error logging entry points for the UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_handlers.h"
+#include "ubsan_diag.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+
+using namespace __sanitizer;
+using namespace __ubsan;
+
+NORETURN void __sanitizer::Die() {
+ __builtin_trap();
+}
+
+NORETURN void __sanitizer::CheckFailed(const char *File, int Line,
+ const char *Cond, u64 V1, u64 V2) {
+ Diag(SourceLocation(File, Line, 0),
+ "CHECK failed: %0 (with values %1 and %2)")
+ << Cond << V1 << V2;
+ Die();
+}
+
+void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
+ ValueHandle Pointer) {
+ const char *TypeCheckKinds[] = {
+ "load of", "store to", "reference binding to", "member access within",
+ "member call on"
+ };
+ if (!Pointer)
+ Diag(Data->Loc, "%0 null pointer of type %1")
+ << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
+ else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
+ Diag(Data->Loc, "%0 misaligned address %1 for type %3, "
+ "which requires %2 byte alignment")
+ << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer
+ << Data->Alignment << Data->Type;
+ else
+ Diag(Data->Loc, "%0 address %1 with insufficient space "
+ "for an object of type %2")
+ << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
+ Die();
+}
+
+/// \brief Common diagnostic emission for various forms of signed overflow.
+template<typename T> static void HandleSignedOverflow(OverflowData *Data,
+ ValueHandle LHS,
+ const char *Operator,
+ T RHS) {
+ Diag(Data->Loc, "signed integer overflow: "
+ "%0 %1 %2 cannot be represented in type %3")
+ << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
+ Die();
+}
+
+void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS) {
+ HandleSignedOverflow(Data, LHS, "+", Value(Data->Type, RHS));
+}
+
+void __ubsan::__ubsan_handle_sub_overflow(OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS) {
+ HandleSignedOverflow(Data, LHS, "-", Value(Data->Type, RHS));
+}
+
+void __ubsan::__ubsan_handle_mul_overflow(OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS) {
+ HandleSignedOverflow(Data, LHS, "*", Value(Data->Type, RHS));
+}
+
+void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
+ ValueHandle OldVal) {
+ Diag(Data->Loc, "negation of %0 cannot be represented in type %1; "
+ "cast to an unsigned type to negate this value to itself")
+ << Value(Data->Type, OldVal) << Data->Type;
+ Die();
+}
+
+void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
+ ValueHandle LHS, ValueHandle RHS) {
+ Value LHSVal(Data->Type, LHS);
+ Value RHSVal(Data->Type, RHS);
+ if (RHSVal.isMinusOne())
+ Diag(Data->Loc, "division of %0 by -1 cannot be represented in type %1")
+ << LHSVal << Data->Type;
+ else
+ Diag(Data->Loc, "division by zero");
+ Die();
+}
+
+void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS) {
+ Value LHSVal(Data->LHSType, LHS);
+ Value RHSVal(Data->RHSType, RHS);
+ if (RHSVal.isNegative())
+ Diag(Data->Loc, "shift exponent %0 is negative") << RHSVal;
+ else if (RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
+ Diag(Data->Loc, "shift exponent %0 is too large for %1-bit type %2")
+ << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
+ else if (LHSVal.isNegative())
+ Diag(Data->Loc, "left shift of negative value %0") << LHSVal;
+ else
+ Diag(Data->Loc, "left shift of %0 by %1 places cannot be represented "
+ "in type %2") << LHSVal << RHSVal << Data->LHSType;
+ Die();
+}
+
+void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
+ Diag(Data->Loc, "execution reached a __builtin_unreachable() call");
+ Die();
+}
+
+void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
+ Diag(Data->Loc, "execution reached the end of a value-returning function "
+ "without returning a value");
+ Die();
+}
Added: compiler-rt/trunk/lib/ubsan/ubsan_handlers.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_handlers.h?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_handlers.h (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_handlers.h Tue Oct 9 14:34:32 2012
@@ -0,0 +1,81 @@
+//===-- ubsan_handlers.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Entry points to the runtime library for Clang's undefined behavior sanitizer.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_HANDLERS_H
+#define UBSAN_HANDLERS_H
+
+#include "ubsan_value.h"
+
+namespace __ubsan {
+
+struct TypeMismatchData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+ uptr Alignment;
+ unsigned char TypeCheckKind;
+};
+
+/// \brief Handle a runtime type check failure, caused by either a misaligned
+/// pointer, a null pointer, or a pointer to insufficient storage for the
+/// type.
+extern "C" void __ubsan_handle_type_mismatch(TypeMismatchData *Data,
+ ValueHandle Pointer);
+
+struct OverflowData {
+ SourceLocation Loc;
+ const TypeDescriptor &Type;
+};
+
+/// \brief Handle a signed integer addition overflow.
+extern "C" void __ubsan_handle_add_overflow(OverflowData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS);
+/// \brief Handle a signed integer subtraction overflow.
+extern "C" void __ubsan_handle_sub_overflow(OverflowData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS);
+/// \brief Handle a signed integer multiplication overflow.
+extern "C" void __ubsan_handle_mul_overflow(OverflowData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS);
+/// \brief Handle a signed integer overflow for a unary negate operator.
+extern "C" void __ubsan_handle_negate_overflow(OverflowData *Data,
+ ValueHandle OldVal);
+/// \brief Handle an INT_MIN/-1 overflow or division by zero.
+extern "C" void __ubsan_handle_divrem_overflow(OverflowData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS);
+
+struct ShiftOutOfBoundsData {
+ SourceLocation Loc;
+ const TypeDescriptor &LHSType;
+ const TypeDescriptor &RHSType;
+};
+
+/// \brief Handle a shift where the RHS is out of bounds or a left shift where
+/// the LHS is negative or overflows.
+extern "C" void __ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
+ ValueHandle LHS,
+ ValueHandle RHS);
+
+struct UnreachableData {
+ SourceLocation Loc;
+};
+
+/// \brief Handle a __builtin_unreachable which is reached.
+extern "C" void __ubsan_handle_builtin_unreachable(UnreachableData *Data);
+/// \brief Handle reaching the end of a value-returning function.
+extern "C" void __ubsan_handle_missing_return(UnreachableData *Data);
+
+}
+
+#endif // UBSAN_HANDLERS_H
Added: compiler-rt/trunk/lib/ubsan/ubsan_value.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_value.cc?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.cc (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.cc Tue Oct 9 14:34:32 2012
@@ -0,0 +1,75 @@
+//===-- ubsan_value.cc ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Representation of a runtime value, as marshaled from the generated code to
+// the ubsan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_value.h"
+
+using namespace __ubsan;
+
+SIntMax Value::getSIntValue() const {
+ CHECK(getType().isSignedIntegerTy());
+ if (isInlineInt()) {
+ // Val was zero-extended to ValueHandle. Sign-extend from original width
+ // to SIntMax.
+ const unsigned ExtraBits =
+ sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
+ return SIntMax(Val) << ExtraBits >> ExtraBits;
+ }
+ if (getType().getIntegerBitWidth() == 64)
+ return *reinterpret_cast<s64*>(Val);
+#ifdef HAVE_INT128_T
+ if (getType().getIntegerBitWidth() == 128)
+ return *reinterpret_cast<s128*>(Val);
+#endif
+ UNREACHABLE("unexpected bit width");
+}
+
+UIntMax Value::getUIntValue() const {
+ CHECK(getType().isUnsignedIntegerTy());
+ if (isInlineInt())
+ return Val;
+ if (getType().getIntegerBitWidth() == 64)
+ return *reinterpret_cast<u64*>(Val);
+#ifdef HAVE_INT128_T
+ if (getType().getIntegerBitWidth() == 128)
+ return *reinterpret_cast<u128*>(Val);
+#endif
+ UNREACHABLE("unexpected bit width");
+}
+
+UIntMax Value::getPositiveIntValue() const {
+ if (getType().isUnsignedIntegerTy())
+ return getUIntValue();
+ SIntMax Val = getSIntValue();
+ CHECK(Val >= 0);
+ return Val;
+}
+
+/// 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 {
+ CHECK(getType().isFloatTy());
+ 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);
+#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);
+ }
+ UNREACHABLE("unexpected floating point bit width");
+}
Added: compiler-rt/trunk/lib/ubsan/ubsan_value.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_value.h?rev=165533&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_value.h (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_value.h Tue Oct 9 14:34:32 2012
@@ -0,0 +1,171 @@
+//===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Representation of data which is passed from the compiler-generated calls into
+// the ubsan runtime.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_VALUE_H
+#define UBSAN_VALUE_H
+
+// For now, only support linux. Other platforms should be easy to add, and
+// probably work as-is.
+#if !defined(__linux__)
+#error "UBSan not supported for this platform!"
+#endif
+
+#include "sanitizer_common/sanitizer_common.h"
+
+// FIXME: Move this out to a config header.
+typedef __int128 s128;
+typedef unsigned __int128 u128;
+#define HAVE_INT128_T 1
+
+
+namespace __ubsan {
+
+/// \brief Largest integer types we support.
+#ifdef HAVE_INT128_T
+typedef s128 SIntMax;
+typedef u128 UIntMax;
+#else
+typedef s64 SIntMax;
+typedef u64 UIntMax;
+#endif
+
+
+/// \brief A description of a source location. This corresponds to Clang's
+/// \c PresumedLoc type.
+class SourceLocation {
+ const char *Filename;
+ u32 Line;
+ u32 Column;
+
+public:
+ SourceLocation(const char *Filename, unsigned Line, unsigned Column)
+ : Filename(Filename), Line(Line), Column(Column) {}
+
+ /// \brief Determine whether the source location is known.
+ bool isInvalid() const { return !Filename; }
+
+ /// \brief Get the presumed filename for the source location.
+ const char *getFilename() const { return Filename; }
+ /// \brief Get the presumed line number.
+ unsigned getLine() const { return Line; }
+ /// \brief Get the column within the presumed line.
+ unsigned getColumn() const { return Column; }
+};
+
+
+/// \brief A description of a type.
+class TypeDescriptor {
+ /// The name of the type, in a format suitable for including in diagnostics.
+ const char *TypeName;
+
+ /// A value from the \c Kind enumeration, specifying what flavor of type we
+ /// have.
+ u16 TypeKind;
+
+ /// A \c Type-specific value providing information which allows us to
+ /// interpret the meaning of a ValueHandle of this type.
+ u16 TypeInfo;
+
+public:
+ enum Kind {
+ /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
+ /// value. Remaining bits are log_2(bit width). The value representation is
+ /// the integer itself if it fits into a ValueHandle, and a pointer to the
+ /// 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.
+ TK_Float = 0x0001,
+ /// Any other type. The value representation is unspecified.
+ TK_Unknown = 0xffff
+ };
+
+ const char *getTypeName() const { return TypeName; }
+
+ Kind getKind() const {
+ return static_cast<Kind>(TypeKind);
+ }
+
+ bool isIntegerTy() const { return getKind() == TK_Integer; }
+ bool isSignedIntegerTy() const {
+ return isIntegerTy() && (TypeInfo & 1);
+ }
+ bool isUnsignedIntegerTy() const {
+ return isIntegerTy() && !(TypeInfo & 1);
+ }
+ unsigned getIntegerBitWidth() const {
+ CHECK(isIntegerTy());
+ return 1 << (TypeInfo >> 1);
+ }
+
+ bool isFloatTy() const { return getKind() == TK_Float; }
+ unsigned getFloatBitWidth() const {
+ CHECK(isFloatTy());
+ return TypeInfo;
+ }
+};
+
+/// \brief An opaque handle to a value.
+typedef uptr ValueHandle;
+
+
+/// \brief Representation of an operand value provided by the instrumented code.
+///
+/// This is a combination of a TypeDescriptor (which is emitted as constant data
+/// as an operand to a handler function) and a ValueHandle (which is passed at
+/// runtime when a check failure occurs).
+class Value {
+ /// The type of the value.
+ const TypeDescriptor &Type;
+ /// The encoded value itself.
+ ValueHandle Val;
+
+ /// Is \c Val a (zero-extended) integer?
+ bool isInlineInt() const {
+ CHECK(getType().isIntegerTy());
+ const unsigned InlineBits = sizeof(ValueHandle) * 8;
+ const unsigned Bits = getType().getIntegerBitWidth();
+ return Bits <= InlineBits;
+ }
+
+public:
+ Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
+
+ const TypeDescriptor &getType() const { return Type; }
+
+ /// \brief Get this value as a signed integer.
+ SIntMax getSIntValue() const;
+
+ /// \brief Get this value as an unsigned integer.
+ UIntMax getUIntValue() const;
+
+ /// \brief Decode this value, which must be a positive or unsigned integer.
+ UIntMax getPositiveIntValue() const;
+
+ /// Is this an integer with value -1?
+ bool isMinusOne() const {
+ return getType().isSignedIntegerTy() && getSIntValue() == -1;
+ }
+
+ /// Is this a negative integer?
+ bool isNegative() const {
+ return getType().isSignedIntegerTy() && getSIntValue() < 0;
+ }
+
+ /// \brief Get this value as a floating-point quantity.
+ long double getFloatValue() const;
+};
+
+} // namespace __ubsan
+
+#endif // UBSAN_VALUE_H
More information about the llvm-commits
mailing list