In the process of trying to get address sanitizer building for arm64 using cl as a cross compiler I encountered a number of issues.
First there isn’t consistent use of _M_ARM64
for example compiler-rt/lib/builtins/cpu_model/aarch64.c:17
should be adapted to
#if !defined(__aarch64__) && !defined(_M_ARM64)
#error This file is intended only for aarch64-based targets
#endif
compiler-rt\lib\builtins\aarch64\lse.S:23
#ifdef __aarch64__ || _M_ARM64
A second issue was the use of __attribute__
for example in compiler-rt\lib\builtins\cpu_model\aarch64.c:33
_Bool __aarch64_have_lse_atomics
__attribute__((visibility("hidden"), nocommon)) = false;
aarch64.c:130
struct {
unsigned long long features;
// As features grows new fields could be added
} __aarch64_cpu_features __attribute__((visibility("hidden"), nocommon));
and
compiler-rt\lib\builtins\aarch64\fp_mode.c
lines 26
CRT_FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode =
CRT_FE_TONEAREST;
probably need a _MSC_VER
with __declspec versions like
__declspec(selectany)
Then there are arm64 specific issues:
compiler-rt\lib\sanitizer_common\sanitizer_atomic_msvc.h
has x86 specific intrinsics it is invoking like _mm_mfence
and _mm_pause
that should probably be __builtin_arm_dmb
and __builtin_arm_yield
.
Similarly, compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h
uses the __ud2 x86 intrinsic that will need an arm64 equivalent for the Trap call.
What is the right approach for inclusion of arm64 intrinsics?
I’m assuming we don’t want something things like
#if defined(__i386__) || defined(__x86_64__)
extern "C" void _mm_mfence();
#pragma intrinsic(_mm_mfence)
extern "C" void _mm_pause();
#pragma intrinsic(_mm_pause)
#endif
#if defined(__aarch64__) || defined(_M_ARM64)
extern "C" void __builtin_arm_dmb();
#pragma intrinsic(__builtin_arm_dmb)
extern "C" void __builtin_arm_yield();
#pragma intrinsic(__builtin_arm_yield)
#endif
#if defined(__i386__) || defined(__x86_64__)
extern "C" void __ud2(void);
# pragma intrinsic(__ud2)
inline void Trap() {
__ud2();
}
#elif defined(__aarch64__) || defined(_M_ARM64)
extern "C" void __builtin_arm_nop(void);
# pragma intrinsic(__builtin_arm_nop)
inline void Trap() {
__builtin_arm_nop();
}
#endif
inline void atomic_thread_fence(memory_order) {
#if defined(__i386__) || defined(__x86_64__)
_mm_mfence();
#elif defined(__aarch64__) || defined(_M_ARM64)
__builtin_arm_dmb();
#endif
}
inline void proc_yield(int cnt) {
for (int i = 0; i < cnt; i++) {
#if defined(__i386__) || defined(__x86_64__)
_mm_pause();
#elif defined(__aarch64__) || defined(_M_ARM64)
__builtin_arm_yield();
#endif
}
}
after all these changes there are a few remaining build issues
Cmake setting:
cmake -G Ninja -DCOMPILER_RT_BUILD_SANITIZERS=ON \
-DCOMPILER_RT_SANITIZERS_TO_BUILD="asan" \
-DLLVM_DEFAULT_TARGET_TRIPLE="aarch64-pc-windows-msvc" \
-S compiler-rt -B ..\build-compiler-rt-cl -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER_TARGET="aarch64-pc-windows-msvc" \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=YES \
-DCOMPILER_RT_INCLUDE_TESTS=FALSE -DCMAKE_SYSTEM_NAME=Windows
ninja -C ..\build-compiler-rt-cl
Almost every line looks something like this:>
cl : Command line warning D9035 : option ‘o’ has been deprecated and will be removed in a future release
cl : Command line warning D9024 : unrecognized source file type ‘D:\projects\build-compiler-rt-cl\lib\builtins\outline_atomic_helpers.dir\outline_atomic_ldclr4_3.S’, object file assumed
cl : Command line warning D9027 : source file ‘D:\projects\build-compiler-rt-cl\lib\builtins\outline_atomic_helpers.dir\outline_atomic_ldclr4_3.S’ ignored
cl : Command line warning D9021 : no action performed
Eventually the build will fail just because of the warnings
ninja: build stopped: subcommand failed.