summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeunsik Lim <leemgs@users.noreply.github.com>2016-07-26 12:59:47 +0900
committerJan Kotas <jkotas@microsoft.com>2016-07-25 20:59:47 -0700
commit561b64d2c210b4d999de7f1ac55756704eaba784 (patch)
tree4d5d88a65317f0b819e549632f9b4c0386c16880 /src
parent6e3c1a63e683b9c825c218efc6d75bf5e430f474 (diff)
downloadcoreclr-561b64d2c210b4d999de7f1ac55756704eaba784.tar.gz
coreclr-561b64d2c210b4d999de7f1ac55756704eaba784.tar.bz2
coreclr-561b64d2c210b4d999de7f1ac55756704eaba784.zip
Linux/ARM: Fix +3000 bus errors of unit-test in case of O2/O3 levels (#6379)
**PROBLEM** This patch is to resolve +3000 bus errors that are generated whenever we use the aggressive optimization levels of clang (issue #5844 ). When we enable the -O3 optimization level of the clang version(from clang 3.5 to clang 3.9(snapshot)), we have always got the lots of bus errors from the coreCLR's unit tests. Actually, we can easily monitor SIGBUS signals (e.g., "misaligned memory access") with /proc/cpu/alignment facility in kernel space. Using "echo 2 > /proc/cpu/alignment" makes Linux kernel fixes the problems but the performance of the application will be degraded. .source: http://lxr.free-electrons.com/source/Documentation/arm/mem_alignment **VERSION 4** . Use 'GET_UNALIGNED_VALXXX' macros in the CoreClr infra-structure without any need for ifdefs. **VERSION 3** .Apply this PR on only Linux/ARM for different system environment (Windows). Here is .NET CI Report on Windows: Compile Error error C2146: syntax error: missing ';' before identifier '__unaligned_int32' (compiling source file D:\j\workspace\checked_windo---f6dc6fe4\src\jit\alloc.cpp) [D:\j\workspace\checked_windo---f6dc6fe4\bin\obj\Windows_NT.x64.Checked\src\jit\ crossgen\clrjit_crossgen.vcxproj] Indication 1 **VERSION 2** .Add UNALIGNED_ARM macro for handling ARM core specific optimization levels. .Add RISC-based ARM core handling into the existing infra-structure of the platform adaptation layer (PAL) for aggressive optimization cases on Linux/ARM. **VERSION 1** Basically, RISC-based ARM architecture requires aligned access with 4byte reads. In order to support aggressive optimization levels such as O2/O3, let's use attribute keyword of aligned(1) instead of using memcpy(2) in into a properly aligned buffer or the packing attribute. **BACKGROUND** According to ARM information center(infocenter.arm.com), By default, the ARM compiler expects normal C and C++ pointers to point to an aligned word in memory. A type qualifier __packed is provided to enable unaligned pointer access. If you want to define a pointer to a word that can be at any address (that is, that can be at a non-natural alignment), you must specify this using the __packed qualifier when defining the pointer: __packed int *pi; // pointer to unaligned int However, clang/llvm does not support the __packed qualifier such as __attribute__((packed)) or __attribute__((packed, aligned(4))) In -O0 (debug build) the innermost block is emitted as the following assembly, which works properly: ldr r1, [r0, #24] ldr r2, [r0, #20] In -O3 (release build) however the compiler realizes these fields are adjacent and generates this assembly: ldrdeq r2, r3, [r0, #20] Unfortunately, vldr/ldrdb instructions always generate an alignment fault (in practice). It seems that clang uses ldrb instruction although GCC uses ldr instruction because armv7 supports unaligned ldr instruction. Note: If some arm architectures (e.g., Linux/ARM Emulator) does not support unaligned ldr, this issue is not generated with aggressive optimization levels (e.g., -O2 and -O3). * Case study: How does the ARM Compiler support unaligned accesses? http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html * Case study: Indicating unaligned access to Clang for ARM compatibility http://stackoverflow.com/questions/9185811/indicating-unaligned-access-to-clang-for-arm-compatibility * Case study: Chromium source for UnalignedLoad32() on ARM https://github.com/nwjs/chromium.src/blob/nw15/third_party/cld/base/basictypes.h#L302 Signed-off-by: Geunsik Lim <geunsik.lim@samsung.com>
Diffstat (limited to 'src')
-rw-r--r--src/jit/compiler.hpp12
-rw-r--r--src/pal/inc/pal_endian.h10
2 files changed, 13 insertions, 9 deletions
diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp
index 6bf7c48f8e..d8ec1aca75 100644
--- a/src/jit/compiler.hpp
+++ b/src/jit/compiler.hpp
@@ -752,27 +752,27 @@ unsigned __int8 getU1LittleEndian(const BYTE * ptr)
inline
unsigned __int16 getU2LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED unsigned __int16 *)ptr; }
+{ return GET_UNALIGNED_VAL16(ptr); }
inline
unsigned __int32 getU4LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED unsigned __int32*)ptr; }
+{ return GET_UNALIGNED_VAL32(ptr); }
inline
signed __int8 getI1LittleEndian(const BYTE * ptr)
-{ return * (UNALIGNED signed __int8 *)ptr; }
+{ return *(UNALIGNED signed __int8 *)ptr; }
inline
signed __int16 getI2LittleEndian(const BYTE * ptr)
-{ return * (UNALIGNED signed __int16 *)ptr; }
+{ return GET_UNALIGNED_VAL16(ptr); }
inline
signed __int32 getI4LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED signed __int32*)ptr; }
+{ return GET_UNALIGNED_VAL32(ptr); }
inline
signed __int64 getI8LittleEndian(const BYTE * ptr)
-{ return *(UNALIGNED signed __int64*)ptr; }
+{ return GET_UNALIGNED_VAL64(ptr); }
inline
float getR4LittleEndian(const BYTE * ptr)
diff --git a/src/pal/inc/pal_endian.h b/src/pal/inc/pal_endian.h
index 8a9032301d..50b9e76765 100644
--- a/src/pal/inc/pal_endian.h
+++ b/src/pal/inc/pal_endian.h
@@ -98,8 +98,12 @@ inline void SwapGuid(GUID *pGuid)
#define VALPTR(x) VAL32(x)
#endif
-#if defined(ALIGN_ACCESS) && !defined(_MSC_VER)
+#ifdef _ARM_
+#define LOG2_PTRSIZE 2
+#define ALIGN_ACCESS ((1<<LOG2_PTRSIZE)-1)
+#endif
+#if defined(ALIGN_ACCESS) && !defined(_MSC_VER)
#ifdef __cplusplus
extern "C++" {
// Get Unaligned values from a potentially unaligned object
@@ -138,7 +142,7 @@ inline void SET_UNALIGNED_64(void *pObject, UINT64 Value)
}
#endif // __cplusplus
-#else
+#else // defined(ALIGN_ACCESS) && !defined(_MSC_VER)
// Get Unaligned values from a potentially unaligned object
#define GET_UNALIGNED_16(_pObject) (*(UINT16 UNALIGNED *)(_pObject))
@@ -150,7 +154,7 @@ inline void SET_UNALIGNED_64(void *pObject, UINT64 Value)
#define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value)
#define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value)
-#endif
+#endif // defined(ALIGN_ACCESS) && !defined(_MSC_VER)
// Get Unaligned values from a potentially unaligned object and swap the value
#define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject))