diff --git a/lib/builtins/arm/aeabi_dcmp.S b/lib/builtins/arm/aeabi_dcmp.S index 51539c0ac813..9fa78b461248 100644 --- a/lib/builtins/arm/aeabi_dcmp.S +++ b/lib/builtins/arm/aeabi_dcmp.S @@ -1,43 +1,52 @@ //===-- aeabi_dcmp.S - EABI dcmp* implementation ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // int __aeabi_dcmp{eq,lt,le,ge,gt}(double a, double b) { // int result = __{eq,lt,le,ge,gt}df2(a, b); // if (result {==,<,<=,>=,>} 0) { // return 1; // } else { // return 0; // } // } +#if defined(COMPILER_RT_ARMHF_TARGET) +# define CONVERT_DCMP_ARGS_TO_DF2_ARGS \ + vmov d0, r0, r1 SEPARATOR \ + vmov d1, r2, r3 +#else +# define CONVERT_DCMP_ARGS_TO_DF2_ARGS +#endif + #define DEFINE_AEABI_DCMP(cond) \ .syntax unified SEPARATOR \ .p2align 2 SEPARATOR \ DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \ push { r4, lr } SEPARATOR \ + CONVERT_DCMP_ARGS_TO_DF2_ARGS SEPARATOR \ bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \ cmp r0, #0 SEPARATOR \ b ## cond 1f SEPARATOR \ movs r0, #0 SEPARATOR \ pop { r4, pc } SEPARATOR \ 1: SEPARATOR \ movs r0, #1 SEPARATOR \ pop { r4, pc } SEPARATOR \ END_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) DEFINE_AEABI_DCMP(eq) DEFINE_AEABI_DCMP(lt) DEFINE_AEABI_DCMP(le) DEFINE_AEABI_DCMP(ge) DEFINE_AEABI_DCMP(gt) NO_EXEC_STACK_DIRECTIVE diff --git a/lib/builtins/arm/aeabi_fcmp.S b/lib/builtins/arm/aeabi_fcmp.S index 8e7774b58974..ea5b96c21d57 100644 --- a/lib/builtins/arm/aeabi_fcmp.S +++ b/lib/builtins/arm/aeabi_fcmp.S @@ -1,43 +1,52 @@ //===-- aeabi_fcmp.S - EABI fcmp* implementation ---------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../assembly.h" // int __aeabi_fcmp{eq,lt,le,ge,gt}(float a, float b) { // int result = __{eq,lt,le,ge,gt}sf2(a, b); // if (result {==,<,<=,>=,>} 0) { // return 1; // } else { // return 0; // } // } +#if defined(COMPILER_RT_ARMHF_TARGET) +# define CONVERT_FCMP_ARGS_TO_SF2_ARGS \ + vmov s0, r0 SEPARATOR \ + vmov s1, r1 +#else +# define CONVERT_FCMP_ARGS_TO_SF2_ARGS +#endif + #define DEFINE_AEABI_FCMP(cond) \ .syntax unified SEPARATOR \ .p2align 2 SEPARATOR \ DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \ push { r4, lr } SEPARATOR \ + CONVERT_FCMP_ARGS_TO_SF2_ARGS SEPARATOR \ bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \ cmp r0, #0 SEPARATOR \ b ## cond 1f SEPARATOR \ movs r0, #0 SEPARATOR \ pop { r4, pc } SEPARATOR \ 1: SEPARATOR \ movs r0, #1 SEPARATOR \ pop { r4, pc } SEPARATOR \ END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) DEFINE_AEABI_FCMP(eq) DEFINE_AEABI_FCMP(lt) DEFINE_AEABI_FCMP(le) DEFINE_AEABI_FCMP(ge) DEFINE_AEABI_FCMP(gt) NO_EXEC_STACK_DIRECTIVE diff --git a/lib/esan/esan_sideline_linux.cpp b/lib/esan/esan_sideline_linux.cpp index d04f5909d6a2..bc272dfe49f8 100644 --- a/lib/esan/esan_sideline_linux.cpp +++ b/lib/esan/esan_sideline_linux.cpp @@ -1,177 +1,177 @@ //===-- esan_sideline_linux.cpp ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of EfficiencySanitizer, a family of performance tuners. // // Support for a separate or "sideline" tool thread on Linux. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_LINUX #include "esan_sideline.h" #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_linux.h" #include #include #include #include #include #include #include namespace __esan { static const int SigAltStackSize = 4*1024; static const int SidelineStackSize = 4*1024; static const uptr SidelineIdUninitialized = 1; // FIXME: we'll need some kind of TLS (can we trust that a pthread key will // work in our non-POSIX thread?) to access our data in our signal handler // with multiple sideline threads. For now we assume there is only one // sideline thread and we use a dirty solution of a global var. static SidelineThread *TheThread; // We aren't passing SA_NODEFER so the same signal is blocked while here. void SidelineThread::handleSidelineSignal(int SigNum, void *SigInfo, void *Ctx) { VPrintf(3, "Sideline signal %d\n", SigNum); CHECK_EQ(SigNum, SIGALRM); // See above about needing TLS to avoid this global var. SidelineThread *Thread = TheThread; if (atomic_load(&Thread->SidelineExit, memory_order_relaxed) != 0) return; Thread->sampleFunc(Thread->FuncArg); } void SidelineThread::registerSignal(int SigNum) { __sanitizer_sigaction SigAct; internal_memset(&SigAct, 0, sizeof(SigAct)); SigAct.sigaction = handleSidelineSignal; // We do not pass SA_NODEFER as we want to block the same signal. SigAct.sa_flags = SA_ONSTACK | SA_SIGINFO; int Res = internal_sigaction(SigNum, &SigAct, nullptr); CHECK_EQ(Res, 0); } int SidelineThread::runSideline(void *Arg) { VPrintf(1, "Sideline thread starting\n"); SidelineThread *Thread = static_cast(Arg); // If the parent dies, we want to exit also. internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // Set up a signal handler on an alternate stack for safety. InternalScopedBuffer StackMap(SigAltStackSize); - struct sigaltstack SigAltStack; + stack_t SigAltStack; SigAltStack.ss_sp = StackMap.data(); SigAltStack.ss_size = SigAltStackSize; SigAltStack.ss_flags = 0; internal_sigaltstack(&SigAltStack, nullptr); // We inherit the signal mask from the app thread. In case // we weren't created at init time, we ensure the mask is empty. __sanitizer_sigset_t SigSet; internal_sigfillset(&SigSet); int Res = internal_sigprocmask(SIG_UNBLOCK, &SigSet, nullptr); CHECK_EQ(Res, 0); registerSignal(SIGALRM); bool TimerSuccess = Thread->adjustTimer(Thread->Freq); CHECK(TimerSuccess); // We loop, doing nothing but handling itimer signals. while (atomic_load(&TheThread->SidelineExit, memory_order_relaxed) == 0) sched_yield(); if (!Thread->adjustTimer(0)) VPrintf(1, "Failed to disable timer\n"); VPrintf(1, "Sideline thread exiting\n"); return 0; } bool SidelineThread::launchThread(SidelineFunc takeSample, void *Arg, u32 FreqMilliSec) { // This can only be called once. However, we can't clear a field in // the constructor and check for that here as the constructor for // a static instance is called *after* our module_ctor and thus after // this routine! Thus we rely on the TheThread check below. CHECK(TheThread == nullptr); // Only one sideline thread is supported. TheThread = this; sampleFunc = takeSample; FuncArg = Arg; Freq = FreqMilliSec; atomic_store(&SidelineExit, 0, memory_order_relaxed); // We do without a guard page. Stack = static_cast(MmapOrDie(SidelineStackSize, "SidelineStack")); // We need to handle the return value from internal_clone() not having been // assigned yet (for our CHECK in adjustTimer()) so we ensure this has a // sentinel value. SidelineId = SidelineIdUninitialized; // By omitting CLONE_THREAD, the child is in its own thread group and will not // receive any of the application's signals. SidelineId = internal_clone( runSideline, Stack + SidelineStackSize, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED, this, nullptr /* parent_tidptr */, nullptr /* newtls */, nullptr /* child_tidptr */); int ErrCode; if (internal_iserror(SidelineId, &ErrCode)) { Printf("FATAL: EfficiencySanitizer failed to spawn a thread (code %d).\n", ErrCode); Die(); return false; // Not reached. } return true; } bool SidelineThread::joinThread() { VPrintf(1, "Joining sideline thread\n"); bool Res = true; atomic_store(&SidelineExit, 1, memory_order_relaxed); while (true) { uptr Status = internal_waitpid(SidelineId, nullptr, __WALL); int ErrCode; if (!internal_iserror(Status, &ErrCode)) break; if (ErrCode == EINTR) continue; VPrintf(1, "Failed to join sideline thread (errno %d)\n", ErrCode); Res = false; break; } UnmapOrDie(Stack, SidelineStackSize); return Res; } // Must be called from the sideline thread itself. bool SidelineThread::adjustTimer(u32 FreqMilliSec) { // The return value of internal_clone() may not have been assigned yet: CHECK(internal_getpid() == SidelineId || SidelineId == SidelineIdUninitialized); Freq = FreqMilliSec; struct itimerval TimerVal; TimerVal.it_interval.tv_sec = (time_t) Freq / 1000; TimerVal.it_interval.tv_usec = (time_t) (Freq % 1000) * 1000; TimerVal.it_value.tv_sec = (time_t) Freq / 1000; TimerVal.it_value.tv_usec = (time_t) (Freq % 1000) * 1000; // As we're in a different thread group, we cannot use either // ITIMER_PROF or ITIMER_VIRTUAL without taking up scheduled // time ourselves: thus we must use real time. int Res = setitimer(ITIMER_REAL, &TimerVal, nullptr); return (Res == 0); } } // namespace __esan #endif // SANITIZER_LINUX diff --git a/lib/profile/InstrProfilingNameVar.c b/lib/profile/InstrProfilingNameVar.c index a0c448c679b5..264568fbc912 100644 --- a/lib/profile/InstrProfilingNameVar.c +++ b/lib/profile/InstrProfilingNameVar.c @@ -1,18 +1,18 @@ -//===- InstrProfilingNameVar.c - profile name variable setup --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// +/*===- InstrProfilingNameVar.c - profile name variable setup -------------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +\*===----------------------------------------------------------------------===*/ #include "InstrProfiling.h" /* char __llvm_profile_filename[1] * * The runtime should only provide its own definition of this symbol when the * user has not specified one. Set this up by moving the runtime's copy of this * symbol to an object file within the archive. */ COMPILER_RT_WEAK char INSTR_PROF_PROFILE_NAME_VAR[1] = {0};