[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