From 282842399f40d4063b5d61f62c2c4cd92c370df8 Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Fri, 5 Oct 2018 11:57:28 +0300 Subject: [PATCH 01/16] [Sanitizers] Disable use-after-scope by default. So, until the patch "Speed up use-after-scope (v2): rewrite into SSA" is not implemented, we set use-after-scope disabled by default. Change-Id: Ia84ce0652ce68bc7c269d72a2a4613cb0806bcf4 --- gcc/opts.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gcc/opts.c b/gcc/opts.c index 1455a14..b159d1e 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -973,12 +973,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_strict_overflow = 0; } - /* Enable -fsanitize-address-use-after-scope if address sanitizer is - enabled. */ - if (opts->x_flag_sanitize - && !opts_set->x_flag_sanitize_address_use_after_scope) - opts->x_flag_sanitize_address_use_after_scope = true; - /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope is enabled. */ if (opts->x_flag_sanitize_address_use_after_scope) -- 2.7.4 From 9373a5031b48bf7e027228d8f836c90ccec9cafe Mon Sep 17 00:00:00 2001 From: Slava Barinov Date: Mon, 22 Oct 2018 11:16:29 +0300 Subject: [PATCH 02/16] Switch off -Wswitch-unreachable by default (move to Wextra) Change-Id: I17f651eadbea96d8a48a72d0be7b345955383b2f Signed-off-by: Slava Barinov --- gcc/common.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/common.opt b/gcc/common.opt index aaaf467..44292ad 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -716,7 +716,7 @@ Common Var(warn_suggest_final_methods) Warning Warn about C++ virtual methods where adding final keyword would improve code quality. Wswitch-unreachable -Common Var(warn_switch_unreachable) Warning Init(1) +Common Var(warn_switch_unreachable) Warning EnabledBy(Wextra) Warn about statements between switch's controlling expression and the first case. -- 2.7.4 From a6217d27848b5257590f552adcfdcc43e171e2ae Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Wed, 22 Aug 2018 13:48:13 +0300 Subject: [PATCH 03/16] packaging: Enable gcc build with mthumb-fp Change-Id: Ib433b7163a1541134ed7bbf4b446a70fb5a2f34a --- packaging/gcc-aarch64.spec | 2 +- packaging/gcc-armv7hl.spec | 2 +- packaging/gcc-armv7l.spec | 2 +- packaging/linaro-gcc.spec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/gcc-aarch64.spec b/packaging/gcc-aarch64.spec index a6b21c7..f5639ac 100644 --- a/packaging/gcc-aarch64.spec +++ b/packaging/gcc-aarch64.spec @@ -698,7 +698,7 @@ echo "" > gcc/DEV-PHASE %{?asan: %gcc_unforce_options %ifarch armv7l -RPM_OPT_FLAGS="$RPM_OPT_FLAGS -marm -Wa,-mimplicit-it=arm -fno-omit-frame-pointer" +RPM_OPT_FLAGS="$RPM_OPT_FLAGS -mthumb -mthumb-fp -Wa,-mimplicit-it=thumb -fno-omit-frame-pointer" %endif } %{?esan:%gcc_unforce_options} diff --git a/packaging/gcc-armv7hl.spec b/packaging/gcc-armv7hl.spec index 022cf6f..122942f4a 100644 --- a/packaging/gcc-armv7hl.spec +++ b/packaging/gcc-armv7hl.spec @@ -698,7 +698,7 @@ echo "" > gcc/DEV-PHASE %{?asan: %gcc_unforce_options %ifarch armv7l -RPM_OPT_FLAGS="$RPM_OPT_FLAGS -marm -Wa,-mimplicit-it=arm -fno-omit-frame-pointer" +RPM_OPT_FLAGS="$RPM_OPT_FLAGS -mthumb -mthumb-fp -Wa,-mimplicit-it=thumb -fno-omit-frame-pointer" %endif } %{?esan:%gcc_unforce_options} diff --git a/packaging/gcc-armv7l.spec b/packaging/gcc-armv7l.spec index 4503e9f..0dbe01f 100644 --- a/packaging/gcc-armv7l.spec +++ b/packaging/gcc-armv7l.spec @@ -698,7 +698,7 @@ echo "" > gcc/DEV-PHASE %{?asan: %gcc_unforce_options %ifarch armv7l -RPM_OPT_FLAGS="$RPM_OPT_FLAGS -marm -Wa,-mimplicit-it=arm -fno-omit-frame-pointer" +RPM_OPT_FLAGS="$RPM_OPT_FLAGS -mthumb -mthumb-fp -Wa,-mimplicit-it=thumb -fno-omit-frame-pointer" %endif } %{?esan:%gcc_unforce_options} diff --git a/packaging/linaro-gcc.spec b/packaging/linaro-gcc.spec index 1ef45d2..9ba11ec 100644 --- a/packaging/linaro-gcc.spec +++ b/packaging/linaro-gcc.spec @@ -695,7 +695,7 @@ echo "" > gcc/DEV-PHASE %{?asan: %gcc_unforce_options %ifarch armv7l -RPM_OPT_FLAGS="$RPM_OPT_FLAGS -marm -Wa,-mimplicit-it=arm -fno-omit-frame-pointer" +RPM_OPT_FLAGS="$RPM_OPT_FLAGS -mthumb -mthumb-fp -Wa,-mimplicit-it=thumb -fno-omit-frame-pointer" %endif } %{?esan:%gcc_unforce_options} -- 2.7.4 From 4cfa03a126cce6e9a6e122659df0a6135479b0bc Mon Sep 17 00:00:00 2001 From: Dongkyun Son Date: Fri, 19 Oct 2018 10:40:34 +0900 Subject: [PATCH 04/16] packaging: set %arm(armv7l and armv7hl) to esan_arch Change-Id: I5afa3a89fe3dbffc71a4883f02ef6ac95fe8eeb4 Signed-off-by: Dongkyun Son --- packaging/gcc-aarch64.spec | 2 +- packaging/gcc-armv7hl.spec | 2 +- packaging/gcc-armv7l.spec | 2 +- packaging/linaro-gcc.spec | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/gcc-aarch64.spec b/packaging/gcc-aarch64.spec index f5639ac..5814a71 100644 --- a/packaging/gcc-aarch64.spec +++ b/packaging/gcc-aarch64.spec @@ -42,7 +42,7 @@ %define quadmath_arch %ix86 x86_64 ia64 %define tsan_arch x86_64 aarch64 -%define esan_arch x86_64 armv7l +%define esan_arch x86_64 %arm %define asan_arch x86_64 %ix86 ppc ppc64 %sparc %arm aarch64 %define itm_arch x86_64 %ix86 %arm ppc ppc64 ppc64le s390 s390x %sparc aarch64 %define atomic_arch x86_64 %ix86 %arm aarch64 ppc ppc64 ppc64le s390 s390x %sparc m68k diff --git a/packaging/gcc-armv7hl.spec b/packaging/gcc-armv7hl.spec index 122942f4a..0b23f93 100644 --- a/packaging/gcc-armv7hl.spec +++ b/packaging/gcc-armv7hl.spec @@ -42,7 +42,7 @@ %define quadmath_arch %ix86 x86_64 ia64 %define tsan_arch x86_64 aarch64 -%define esan_arch x86_64 armv7l +%define esan_arch x86_64 %arm %define asan_arch x86_64 %ix86 ppc ppc64 %sparc %arm aarch64 %define itm_arch x86_64 %ix86 %arm ppc ppc64 ppc64le s390 s390x %sparc aarch64 %define atomic_arch x86_64 %ix86 %arm aarch64 ppc ppc64 ppc64le s390 s390x %sparc m68k diff --git a/packaging/gcc-armv7l.spec b/packaging/gcc-armv7l.spec index 0dbe01f..8f7e676 100644 --- a/packaging/gcc-armv7l.spec +++ b/packaging/gcc-armv7l.spec @@ -42,7 +42,7 @@ %define quadmath_arch %ix86 x86_64 ia64 %define tsan_arch x86_64 aarch64 -%define esan_arch x86_64 armv7l +%define esan_arch x86_64 %arm %define asan_arch x86_64 %ix86 ppc ppc64 %sparc %arm aarch64 %define itm_arch x86_64 %ix86 %arm ppc ppc64 ppc64le s390 s390x %sparc aarch64 %define atomic_arch x86_64 %ix86 %arm aarch64 ppc ppc64 ppc64le s390 s390x %sparc m68k diff --git a/packaging/linaro-gcc.spec b/packaging/linaro-gcc.spec index 9ba11ec..2401252 100644 --- a/packaging/linaro-gcc.spec +++ b/packaging/linaro-gcc.spec @@ -39,7 +39,7 @@ %define quadmath_arch %ix86 x86_64 ia64 %define tsan_arch x86_64 aarch64 -%define esan_arch x86_64 armv7l +%define esan_arch x86_64 %arm %define asan_arch x86_64 %ix86 ppc ppc64 %sparc %arm aarch64 %define itm_arch x86_64 %ix86 %arm ppc ppc64 ppc64le s390 s390x %sparc aarch64 %define atomic_arch x86_64 %ix86 %arm aarch64 ppc ppc64 ppc64le s390 s390x %sparc m68k -- 2.7.4 From 693be6f4718f42483155cafbc3e3122cca49141e Mon Sep 17 00:00:00 2001 From: Mikhail Kashkarov Date: Fri, 26 Oct 2018 22:06:18 +0300 Subject: [PATCH 05/16] Move asan/pr80659.c to gcc/testsuite folder Fix testcase placement after e2cd7f1b Change-Id: Idd0d622ca66573c5a8005d139fbbff033bc8abe3 --- {testsuite => gcc/testsuite}/gcc.dg/asan/pr80659.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {testsuite => gcc/testsuite}/gcc.dg/asan/pr80659.c (100%) diff --git a/testsuite/gcc.dg/asan/pr80659.c b/gcc/testsuite/gcc.dg/asan/pr80659.c similarity index 100% rename from testsuite/gcc.dg/asan/pr80659.c rename to gcc/testsuite/gcc.dg/asan/pr80659.c -- 2.7.4 From eb8a27c4157d7944cccdbdfac4f5f7a295bf2ee2 Mon Sep 17 00:00:00 2001 From: Alex Shlyapnikov Date: Mon, 15 May 2017 23:11:01 +0000 Subject: [PATCH 06/16] [LSan] Report the missing linker only when the linker is actually missing. Reviewers: eugenis Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D33218 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@303129 91177308-0d34-0410-b5e6-96231b3b80d8 Backport: http://llvm.org/git/compiler-rt 4ba4036 Change-Id: I1c01e8679206af77fcd971a8fed5b8dde0e42b15 --- libsanitizer/lsan/lsan_common_linux.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsanitizer/lsan/lsan_common_linux.cc b/libsanitizer/lsan/lsan_common_linux.cc index d49c3c0..f63b891 100644 --- a/libsanitizer/lsan/lsan_common_linux.cc +++ b/libsanitizer/lsan/lsan_common_linux.cc @@ -49,8 +49,10 @@ void InitializePlatformSpecificModules() { return; } } - VReport(1, "LeakSanitizer: Dynamic linker not found. " - "TLS will not be handled correctly.\n"); + if (linker == nullptr) { + VReport(1, "LeakSanitizer: Dynamic linker not found. " + "TLS will not be handled correctly.\n"); + } } static int ProcessGlobalRegionsCallback(struct dl_phdr_info *info, size_t size, -- 2.7.4 From 446908d74aabb0048636a8b97476ed95918fd7be Mon Sep 17 00:00:00 2001 From: Francis Ricci Date: Thu, 25 Oct 2018 14:26:37 +0300 Subject: [PATCH 07/16] [LSan] Factor lsan allocator cache accesses into a function Summary: This patch is the first step towards allows us to move away from using __thread for the allocator cache on darwin, which is requiring for building lsan for darwin on ios version 7 and on iossim i386. This will be followed by patches to move the function into OS-specific files. Reviewers: kubamracek, kcc Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29994 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@298537 91177308-0d34-0410-b5e6-96231b3b80d8 Backport: http://llvm.org/git/compiler-rt 65ede46c Change-Id: Icd528cc4e96c63489c7d25cbb3af100a32d4a26f Signed-off-by: Vyacheslav Cherkashin --- libsanitizer/lsan/lsan_allocator.cc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc index 2203506..e711766 100644 --- a/libsanitizer/lsan/lsan_allocator.cc +++ b/libsanitizer/lsan/lsan_allocator.cc @@ -76,7 +76,8 @@ typedef CombinedAllocator Allocator; static Allocator allocator; -static THREADLOCAL AllocatorCache cache; +static THREADLOCAL AllocatorCache allocator_cache; +AllocatorCache *GetAllocatorCache() { return &allocator_cache; } void InitializeAllocator() { SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); @@ -85,7 +86,7 @@ void InitializeAllocator() { } void AllocatorThreadFinish() { - allocator.SwallowCache(&cache); + allocator.SwallowCache(GetAllocatorCache()); } static ChunkMetadata *Metadata(const void *p) { @@ -117,7 +118,7 @@ void *Allocate(const StackTrace &stack, uptr size, uptr alignment, Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", size); return nullptr; } - void *p = allocator.Allocate(&cache, size, alignment); + void *p = allocator.Allocate(GetAllocatorCache(), size, alignment); // Do not rely on the allocator to clear the memory (it's slow). if (cleared && allocator.FromPrimary(p)) memset(p, 0, size); @@ -131,7 +132,7 @@ void Deallocate(void *p) { if (&__sanitizer_free_hook) __sanitizer_free_hook(p); RunFreeHooks(p); RegisterDeallocation(p); - allocator.Deallocate(&cache, p); + allocator.Deallocate(GetAllocatorCache(), p); } void *Reallocate(const StackTrace &stack, void *p, uptr new_size, @@ -139,17 +140,17 @@ void *Reallocate(const StackTrace &stack, void *p, uptr new_size, RegisterDeallocation(p); if (new_size > kMaxAllowedMallocSize) { Report("WARNING: LeakSanitizer failed to allocate %zu bytes\n", new_size); - allocator.Deallocate(&cache, p); + allocator.Deallocate(GetAllocatorCache(), p); return nullptr; } - p = allocator.Reallocate(&cache, p, new_size, alignment); + p = allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment); RegisterAllocation(stack, p, new_size); return p; } void GetAllocatorCacheRange(uptr *begin, uptr *end) { - *begin = (uptr)&cache; - *end = *begin + sizeof(cache); + *begin = (uptr)GetAllocatorCache(); + *end = *begin + sizeof(AllocatorCache); } uptr GetMallocUsableSize(const void *p) { -- 2.7.4 From eeee3b9cb9bc61aa4628bc2f4231098bcb053cf0 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Wed, 31 Oct 2018 17:52:22 +0300 Subject: [PATCH 08/16] [LSan] Add dynamic loading support for LSan library The LSan library has very big static TLS section Problem: - LSan library could not be loaded dynamically because it had a very big static TLS section. AllocatorCache: ~15KB for 32bit ~53KB for 64bit Solution: - Store in the TLS section only a pointer to the AllocatorCache and dynamically allocate memory for it. Change-Id: I6e90e6682e277c90825938f5732867b6564d62b4 Signed-off-by: Vyacheslav Cherkashin --- libsanitizer/lsan/lsan_allocator.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc index e711766..00b6a15 100644 --- a/libsanitizer/lsan/lsan_allocator.cc +++ b/libsanitizer/lsan/lsan_allocator.cc @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_stacktrace.h" +#include "sanitizer_common/sanitizer_allocator_internal.h" #include "lsan_common.h" extern "C" void *memset(void *ptr, int value, uptr num); @@ -76,8 +77,15 @@ typedef CombinedAllocator Allocator; static Allocator allocator; -static THREADLOCAL AllocatorCache allocator_cache; -AllocatorCache *GetAllocatorCache() { return &allocator_cache; } +static THREADLOCAL AllocatorCache *allocator_cache; +AllocatorCache *GetAllocatorCache() { + if (UNLIKELY(allocator_cache == nullptr)) { + // We will not release the memory because the library is not unloaded. + allocator_cache = (AllocatorCache *)InternalAlloc(sizeof(*allocator_cache)); + *allocator_cache = AllocatorCache(); + } + return allocator_cache; +} void InitializeAllocator() { SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); -- 2.7.4 From cc9aad0498fccd587a4c697701446d952c69e557 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Wed, 12 Dec 2018 18:11:52 +0300 Subject: [PATCH 09/16] [LSan] Export a LSan API for use it third party This API is needed to use LSan in conjunction with SWAP Change-Id: Iff1ceaca9242a889b0b68f672302f8a0b3808411 Signed-off-by: Vyacheslav Cherkashin --- libsanitizer/include/sanitizer/lsan_interface.h | 19 ++++++++++++++++ libsanitizer/lsan/lsan.cc | 5 +++++ libsanitizer/lsan/lsan.h | 15 ++++++++++--- libsanitizer/lsan/lsan_allocator.cc | 26 ++++++++++++++++++++++ .../sanitizer_allocator_combined.h | 2 +- 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/libsanitizer/include/sanitizer/lsan_interface.h b/libsanitizer/include/sanitizer/lsan_interface.h index bdbe390..7cdffda 100644 --- a/libsanitizer/include/sanitizer/lsan_interface.h +++ b/libsanitizer/include/sanitizer/lsan_interface.h @@ -67,6 +67,25 @@ extern "C" { // This function may be optionally provided by the user and should return // a string containing LSan suppressions. const char *__lsan_default_suppressions(); + + // Check a pointer belongs to the LSan allocator. + // 0 - not belong + // 1 - belong + int __lsan_allocator_pointer_is_mine(const void *p); + + // Allocate memory using LSan allocator. + void *__lsan_allocator_allocate(size_t size, size_t alignment, int cleared, + unsigned long caller_pc, unsigned long frame); + + // Deallocate memory using LSan allocator. + void __lsan_allocator_deallocate(void *p); + + // Reallocate memory using LSan allocator. + void *__lsan_allocator_reallocate(void *p, size_t new_size, size_t alignment, + unsigned long caller_pc, unsigned long frame); + + // Get LSan report file. + const char *__lsan_report_file(); #ifdef __cplusplus } // extern "C" diff --git a/libsanitizer/lsan/lsan.cc b/libsanitizer/lsan/lsan.cc index 6b68c61..b306734 100644 --- a/libsanitizer/lsan/lsan.cc +++ b/libsanitizer/lsan/lsan.cc @@ -121,3 +121,8 @@ void __sanitizer_print_stack_trace() { GET_STACK_TRACE_FATAL; stack.Print(); } + +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +const char *__lsan_report_file() { + return report_file.full_path; +} diff --git a/libsanitizer/lsan/lsan.h b/libsanitizer/lsan/lsan.h index 881958e..4b4ede73 100644 --- a/libsanitizer/lsan/lsan.h +++ b/libsanitizer/lsan/lsan.h @@ -10,10 +10,11 @@ // //===----------------------------------------------------------------------===// +#include "lsan_thread.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" -#define GET_STACK_TRACE(max_size, fast) \ +#define GET_STACK_TRACE_RAW(caller_pc, frame, max_size, fast) \ BufferedStackTrace stack; \ { \ uptr stack_top = 0, stack_bottom = 0; \ @@ -23,12 +24,15 @@ stack_bottom = t->stack_begin(); \ } \ if (!SANITIZER_MIPS || \ - IsValidFrame(GET_CURRENT_FRAME(), stack_top, stack_bottom)) { \ - stack.Unwind(max_size, StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \ + IsValidFrame(frame, stack_top, stack_bottom)) { \ + stack.Unwind(max_size, caller_pc, frame, \ /* context */ 0, stack_top, stack_bottom, fast); \ } \ } +#define GET_STACK_TRACE(max_size, fast) \ + GET_STACK_TRACE_RAW(GET_CALLER_PC(), GET_CURRENT_FRAME(), max_size, fast) + #define GET_STACK_TRACE_FATAL \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) @@ -36,6 +40,11 @@ GET_STACK_TRACE(__sanitizer::common_flags()->malloc_context_size, \ common_flags()->fast_unwind_on_malloc) +#define GET_STACK_TRACE_MALLOC_RAW(caller_pc, frame) \ + GET_STACK_TRACE_RAW(caller_pc, frame, \ + __sanitizer::common_flags()->malloc_context_size, \ + common_flags()->fast_unwind_on_malloc) + #ifndef LSAN_DYNAMIC # ifdef PIC # define LSAN_DYNAMIC 1 diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc index 00b6a15..a20d1eb 100644 --- a/libsanitizer/lsan/lsan_allocator.cc +++ b/libsanitizer/lsan/lsan_allocator.cc @@ -19,6 +19,7 @@ #include "sanitizer_common/sanitizer_stacktrace.h" #include "sanitizer_common/sanitizer_allocator_internal.h" #include "lsan_common.h" +#include "lsan.h" extern "C" void *memset(void *ptr, int value, uptr num); @@ -284,4 +285,29 @@ SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_allocated_size(const void *p) { return GetMallocUsableSize(p); } + +// LSan allocator API +SANITIZER_INTERFACE_ATTRIBUTE +int __lsan_allocator_pointer_is_mine(const void *p) { + return allocator.PointerIsMine(p); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void *__lsan_allocator_allocate(uptr size, uptr alignment, int cleared, + unsigned long caller_pc, unsigned long frame) { + GET_STACK_TRACE_MALLOC_RAW(caller_pc, frame); + return Allocate(stack, size, alignment, cleared); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void __lsan_allocator_deallocate(void *p) { + Deallocate(p); +} + +SANITIZER_INTERFACE_ATTRIBUTE +void *__lsan_allocator_reallocate(void *p, uptr new_size, uptr alignment, + unsigned long caller_pc, unsigned long frame) { + GET_STACK_TRACE_MALLOC_RAW(caller_pc, frame); + return Reallocate(stack, p, new_size, alignment); +} } // extern "C" diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator_combined.h b/libsanitizer/sanitizer_common/sanitizer_allocator_combined.h index 3b408d5..118a6aa 100644 --- a/libsanitizer/sanitizer_common/sanitizer_allocator_combined.h +++ b/libsanitizer/sanitizer_common/sanitizer_allocator_combined.h @@ -101,7 +101,7 @@ class CombinedAllocator { return new_p; } - bool PointerIsMine(void *p) { + bool PointerIsMine(const void *p) { if (primary_.PointerIsMine(p)) return true; return secondary_.PointerIsMine(p); -- 2.7.4 From aee3a9dfba8152e7f5a77f9d054486ffa51f2d29 Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Fri, 14 Sep 2018 13:43:20 +0300 Subject: [PATCH 10/16] [ESan] Fix typo for the testsuite. Change-Id: I4fc5c6f0978b4be6aa286c42e06b34c687574a6c --- gcc/testsuite/g++.dg/esan/{unalignet.C => unaligned.C} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename gcc/testsuite/g++.dg/esan/{unalignet.C => unaligned.C} (100%) diff --git a/gcc/testsuite/g++.dg/esan/unalignet.C b/gcc/testsuite/g++.dg/esan/unaligned.C similarity index 100% rename from gcc/testsuite/g++.dg/esan/unalignet.C rename to gcc/testsuite/g++.dg/esan/unaligned.C -- 2.7.4 From 02fe217aae2dfd746e3bb4781cc304b0ad1abe7d Mon Sep 17 00:00:00 2001 From: ktkachov Date: Mon, 17 Oct 2016 16:37:38 +0000 Subject: [PATCH 11/16] [AArch64] Use new target pass registration framework for FMA steering pass * config/aarch64/aarch64.c: Delete inclusion of cortex-a57-fma-steering.h. (aarch64_override_options): Delete call to aarch64_register_fma_steering. * config/aarch64/aarch64-protos.h (make_pass_fma_steering): Declare. * config/aarch64/cortex-a57-fma-steering.h: Delete. * config/aarch64/aarch64-passes.def: New file. * config/aarch64/cortex-a57-fma-steering.c (aarch64_register_fma_steering): Delete definition. (make_pass_fma_steering): Remove static qualifier. * config/aarch64/t-aarch64 (PASSES_EXTRA): New directive. (cortex-a57-fma-steering.o): Remove dependency on cortex-a57-fma-steering.h. (backported e8ebfb45f2e320c6a1e810c9d7ca1c40e2b26e6b) Change-Id: I608f6d880296473c76c203e387c96791be9e50f2 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@241248 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 16 ++++++++++++++++ .../{cortex-a57-fma-steering.h => aarch64-passes.def} | 7 +++---- gcc/config/aarch64/aarch64-protos.h | 2 ++ gcc/config/aarch64/aarch64.c | 4 ---- gcc/config/aarch64/cortex-a57-fma-steering.c | 16 +--------------- gcc/config/aarch64/t-aarch64 | 3 ++- 6 files changed, 24 insertions(+), 24 deletions(-) rename gcc/config/aarch64/{cortex-a57-fma-steering.h => aarch64-passes.def} (78%) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4c5f9a6..d85f9d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2016-10-17 Kyrylo Tkachov + + * config/aarch64/aarch64.c: Delete inclusion of + cortex-a57-fma-steering.h. + (aarch64_override_options): Delete call + to aarch64_register_fma_steering. + * config/aarch64/aarch64-protos.h (make_pass_fma_steering): Declare. + * config/aarch64/cortex-a57-fma-steering.h: Delete. + * config/aarch64/aarch64-passes.def: New file. + * config/aarch64/cortex-a57-fma-steering.c + (aarch64_register_fma_steering): Delete definition. + (make_pass_fma_steering): Remove static qualifier. + * config/aarch64/t-aarch64 (PASSES_EXTRA): New directive. + (cortex-a57-fma-steering.o): Remove dependency on + cortex-a57-fma-steering.h. + 2017-07-06 Vyacheslav Barinov * tree.def: Add STATEMENT_LIST_END tree code. diff --git a/gcc/config/aarch64/cortex-a57-fma-steering.h b/gcc/config/aarch64/aarch64-passes.def similarity index 78% rename from gcc/config/aarch64/cortex-a57-fma-steering.h rename to gcc/config/aarch64/aarch64-passes.def index 65bf5ac..7fe8039 100644 --- a/gcc/config/aarch64/cortex-a57-fma-steering.h +++ b/gcc/config/aarch64/aarch64-passes.def @@ -1,6 +1,5 @@ -/* This file contains declarations for the FMA steering optimization - pass for Cortex-A57. - Copyright (C) 2015-2016 Free Software Foundation, Inc. +/* AArch64-specific passes declarations. + Copyright (C) 2016 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of GCC. @@ -19,4 +18,4 @@ along with GCC; see the file COPYING3. If not see . */ -void aarch64_register_fma_steering (void); +INSERT_PASS_AFTER (pass_regrename, 1, pass_fma_steering); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index f270138..23ac210 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -466,4 +466,6 @@ enum aarch64_parse_opt_result aarch64_parse_extension (const char *, std::string aarch64_get_extension_string_for_isa_flags (unsigned long, unsigned long); +rtl_opt_pass *make_pass_fma_steering (gcc::context *ctxt); + #endif /* GCC_AARCH64_PROTOS_H */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index bd75ef2..a1db946 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -62,7 +62,6 @@ #include "rtl-iter.h" #include "tm-constrs.h" #include "sched-int.h" -#include "cortex-a57-fma-steering.h" #include "target-globals.h" #include "common/common-target.h" @@ -8586,9 +8585,6 @@ aarch64_override_options (void) while processing functions with potential target attributes. */ target_option_default_node = target_option_current_node = build_target_option_node (&global_options); - - aarch64_register_fma_steering (); - } /* Implement targetm.override_options_after_change. */ diff --git a/gcc/config/aarch64/cortex-a57-fma-steering.c b/gcc/config/aarch64/cortex-a57-fma-steering.c index 1bf804b..b5f329f 100644 --- a/gcc/config/aarch64/cortex-a57-fma-steering.c +++ b/gcc/config/aarch64/cortex-a57-fma-steering.c @@ -35,7 +35,6 @@ #include "context.h" #include "tree-pass.h" #include "regrename.h" -#include "cortex-a57-fma-steering.h" #include "aarch64-protos.h" /* For better performance, the destination of FMADD/FMSUB instructions should @@ -1068,21 +1067,8 @@ public: /* Create a new fma steering pass instance. */ -static rtl_opt_pass * +rtl_opt_pass * make_pass_fma_steering (gcc::context *ctxt) { return new pass_fma_steering (ctxt); } - -/* Register the FMA steering pass to the pass manager. */ - -void -aarch64_register_fma_steering () -{ - opt_pass *pass_fma_steering = make_pass_fma_steering (g); - - struct register_pass_info fma_steering_info - = { pass_fma_steering, "rnreg", 1, PASS_POS_INSERT_AFTER }; - - register_pass (&fma_steering_info); -} diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64 index 1ba8a5d..b461eb5 100644 --- a/gcc/config/aarch64/t-aarch64 +++ b/gcc/config/aarch64/t-aarch64 @@ -56,12 +56,13 @@ aarch64-c.o: $(srcdir)/config/aarch64/aarch64-c.c $(CONFIG_H) $(SYSTEM_H) \ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/aarch64/aarch64-c.c +PASSES_EXTRA += $(srcdir)/config/aarch64/aarch64-passes.def + cortex-a57-fma-steering.o: $(srcdir)/config/aarch64/cortex-a57-fma-steering.c \ $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \ dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \ output.h hash-map.h $(DF_H) $(OBSTACK_H) $(TARGET_H) $(RTL_H) \ $(CONTEXT_H) $(TREE_PASS_H) regrename.h \ - $(srcdir)/config/aarch64/cortex-a57-fma-steering.h \ $(srcdir)/config/aarch64/aarch64-protos.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/aarch64/cortex-a57-fma-steering.c -- 2.7.4 From 439de83cb9c410a9dd52d4683a6b38438c80c1f7 Mon Sep 17 00:00:00 2001 From: ktkachov Date: Tue, 14 Feb 2017 10:33:50 +0000 Subject: [PATCH 12/16] [ARM] PR rtl-optimization/68664 Implement TARGET_SCHED_CAN_SPECULATE_INSN hook PR rtl-optimization/68664 * config/arm/arm.c (arm_sched_can_speculate_insn): New function. Declare prototype. (TARGET_SCHED_CAN_SPECULATE_INSN): Define. (backported a705f613f2fe0ff13b18fdf92af1dc5574c963d3) Change-Id: I1eb8f369ebf3d85662df78e9da62cf0be35d8b5a git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@245425 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++++ gcc/config/arm/arm.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d85f9d9..b389af4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-02-14 Kyrylo Tkachov + + PR rtl-optimization/68664 + * config/arm/arm.c (arm_sched_can_speculate_insn): + New function. Declare prototype. + (TARGET_SCHED_CAN_SPECULATE_INSN): Define. + 2016-10-17 Kyrylo Tkachov * config/aarch64/aarch64.c: Delete inclusion of diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 181c304..ae21d1a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -238,6 +238,7 @@ static bool arm_can_inline_p (tree, tree); static void arm_relayout_function (tree); static bool arm_valid_target_attribute_p (tree, tree, tree, int); static unsigned HOST_WIDE_INT arm_shift_truncation_mask (machine_mode); +static bool arm_sched_can_speculate_insn (rtx_insn *); static bool arm_macro_fusion_p (void); static bool arm_cannot_copy_insn_p (rtx_insn *); static int arm_issue_rate (void); @@ -412,6 +413,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_COMP_TYPE_ATTRIBUTES #define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes +#undef TARGET_SCHED_CAN_SPECULATE_INSN +#define TARGET_SCHED_CAN_SPECULATE_INSN arm_sched_can_speculate_insn + #undef TARGET_SCHED_MACRO_FUSION_P #define TARGET_SCHED_MACRO_FUSION_P arm_macro_fusion_p @@ -30066,6 +30070,35 @@ arm_fusion_enabled_p (tune_params::fuse_ops op) return current_tune->fusible_ops & op; } +/* Implement TARGET_SCHED_CAN_SPECULATE_INSN. Return true if INSN can be + scheduled for speculative execution. Reject the long-running division + and square-root instructions. */ + +static bool +arm_sched_can_speculate_insn (rtx_insn *insn) +{ + switch (get_attr_type (insn)) + { + case TYPE_SDIV: + case TYPE_UDIV: + case TYPE_FDIVS: + case TYPE_FDIVD: + case TYPE_FSQRTS: + case TYPE_FSQRTD: + case TYPE_NEON_FP_SQRT_S: + case TYPE_NEON_FP_SQRT_D: + case TYPE_NEON_FP_SQRT_S_Q: + case TYPE_NEON_FP_SQRT_D_Q: + case TYPE_NEON_FP_DIV_S: + case TYPE_NEON_FP_DIV_D: + case TYPE_NEON_FP_DIV_S_Q: + case TYPE_NEON_FP_DIV_D_Q: + return false; + default: + return true; + } +} + /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ static unsigned HOST_WIDE_INT -- 2.7.4 From 81c87ae477be33caa487ee363c0d58a494fcd487 Mon Sep 17 00:00:00 2001 From: ktkachov Date: Fri, 2 Jun 2017 14:41:52 +0000 Subject: [PATCH 13/16] [AArch64] Emit tighter strong atomic compare-exchange loop when comparing against zero * config/aarch64/aarch64.c (aarch64_split_compare_and_swap): Emit CBNZ inside loop when doing a strong exchange and comparing against zero. Generate the CC flags after the loop. * gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c: New test. (backported c5dcf8e544c5e98f1160ec390111b28d11d73b68) git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@248832 138bc75d-0d04-0410-961f-82ee72b054a4 Change-Id: I5204c56a8d3c11b0fde6697007d601cbafdb3ccf --- gcc/ChangeLog | 6 ++++ gcc/config/aarch64/aarch64.c | 41 ++++++++++++++++++---- gcc/testsuite/ChangeLog | 4 +++ .../aarch64/atomic_cmp_exchange_zero_strong_1.c | 12 +++++++ 4 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b389af4..76eb226 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-06-02 Kyrylo Tkachov + + * config/aarch64/aarch64.c (aarch64_split_compare_and_swap): + Emit CBNZ inside loop when doing a strong exchange and comparing + against zero. Generate the CC flags after the loop. + 2017-02-14 Kyrylo Tkachov PR rtl-optimization/68664 diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index a1db946..795033f 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -11621,6 +11621,17 @@ aarch64_split_compare_and_swap (rtx operands[]) mode = GET_MODE (mem); model = memmodel_from_int (INTVAL (model_rtx)); + /* When OLDVAL is zero and we want the strong version we can emit a tighter + loop: + .label1: + LD[A]XR rval, [mem] + CBNZ rval, .label2 + ST[L]XR scratch, newval, [mem] + CBNZ scratch, .label1 + .label2: + CMP rval, 0. */ + bool strong_zero_p = !is_weak && oldval == const0_rtx; + label1 = NULL; if (!is_weak) { @@ -11637,11 +11648,21 @@ aarch64_split_compare_and_swap (rtx operands[]) else aarch64_emit_load_exclusive (mode, rval, mem, model_rtx); - cond = aarch64_gen_compare_reg (NE, rval, oldval); - x = gen_rtx_NE (VOIDmode, cond, const0_rtx); - x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, - gen_rtx_LABEL_REF (Pmode, label2), pc_rtx); - aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); + if (strong_zero_p) + { + x = gen_rtx_NE (VOIDmode, rval, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, + gen_rtx_LABEL_REF (Pmode, label2), pc_rtx); + aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); + } + else + { + cond = aarch64_gen_compare_reg (NE, rval, oldval); + x = gen_rtx_NE (VOIDmode, cond, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, + gen_rtx_LABEL_REF (Pmode, label2), pc_rtx); + aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); + } aarch64_emit_store_exclusive (mode, scratch, mem, newval, model_rtx); @@ -11660,7 +11681,15 @@ aarch64_split_compare_and_swap (rtx operands[]) } emit_label (label2); - + /* If we used a CBNZ in the exchange loop emit an explicit compare with RVAL + to set the condition flags. If this is not used it will be removed by + later passes. */ + if (strong_zero_p) + { + cond = gen_rtx_REG (CCmode, CC_REGNUM); + x = gen_rtx_COMPARE (CCmode, rval, const0_rtx); + emit_insn (gen_rtx_SET (cond, x)); + } /* Emit any final barrier needed for a __sync operation. */ if (is_mm_sync (model)) aarch64_emit_post_barrier (model); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fcfdf84..f3714bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-06-02 Kyrylo Tkachov + + * gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c: New test. + 2017-07-06 Vyacheslav Barinov * g++.dg/ext/statement-list-end.C: New. diff --git a/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c new file mode 100644 index 0000000..b14a7c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int +foo (int *a) +{ + int x = 0; + return __atomic_compare_exchange_n (a, &x, 4, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); +} + +/* { dg-final { scan-assembler-times "cbnz\\tw\[0-9\]+" 2 } } */ -- 2.7.4 From 839e47f64150c6130cfdbf6bd43cfc04df3ac286 Mon Sep 17 00:00:00 2001 From: rearnsha Date: Tue, 31 Jul 2018 17:35:32 +0000 Subject: [PATCH 14/16] Add __builtin_speculation_safe_value This patch defines a new intrinsic function __builtin_speculation_safe_value. A generic default implementation is defined which will attempt to use the backend pattern "speculation_safe_barrier". If this pattern is not defined, or if it is not available, then the compiler will emit a warning, but compilation will continue. Note that the test spec-barrier-1.c will currently fail on all targets. This is deliberate, the failure will go away when appropriate action is taken for each target backend. gcc: * builtin-types.def (BT_FN_PTR_PTR_VAR): New function type. (BT_FN_I1_I1_VAR, BT_FN_I2_I2_VAR, BT_FN_I4_I4_VAR): Likewise. (BT_FN_I8_I8_VAR, BT_FN_I16_I16_VAR): Likewise. * builtin-attrs.def (ATTR_NOVOPS_NOTHROW_LEAF_LIST): New attribute list. * builtins.def (BUILT_IN_SPECULATION_SAFE_VALUE_N): New builtin. (BUILT_IN_SPECULATION_SAFE_VALUE_PTR): New internal builtin. (BUILT_IN_SPECULATION_SAFE_VALUE_1): Likewise. (BUILT_IN_SPECULATION_SAFE_VALUE_2): Likewise. (BUILT_IN_SPECULATION_SAFE_VALUE_4): Likewise. (BUILT_IN_SPECULATION_SAFE_VALUE_8): Likewise. (BUILT_IN_SPECULATION_SAFE_VALUE_16): Likewise. * builtins.c (expand_speculation_safe_value): New function. (expand_builtin): Call it. * doc/cpp.texi: Document predefine __HAVE_SPECULATION_SAFE_VALUE. * doc/extend.texi: Document __builtin_speculation_safe_value. * doc/md.texi: Document "speculation_barrier" pattern. * doc/tm.texi.in: Pull in TARGET_SPECULATION_SAFE_VALUE and TARGET_HAVE_SPECULATION_SAFE_VALUE. * doc/tm.texi: Regenerated. * target.def (have_speculation_safe_value, speculation_safe_value): New hooks. * targhooks.c (default_have_speculation_safe_value): New function. (default_speculation_safe_value): New function. * targhooks.h (default_have_speculation_safe_value): Add prototype. (default_speculation_safe_value): Add prototype. c-family: * c-common.c (speculation_safe_resolve_call): New function. (speculation_safe_resolve_params): New function. (speculation_safe_resolve_return): New function. (resolve_overloaded_builtin): Handle __builtin_speculation_safe_value. * c-cppbuiltin.c (c_cpp_builtins): Add pre-define for __HAVE_SPECULATION_SAFE_VALUE. testsuite: * c-c++-common/spec-barrier-1.c: New test. * c-c++-common/spec-barrier-2.c: New test. * gcc.dg/spec-barrier-3.c: New test. (backported 123081efd41261af8830d6c796a9b12435806bac) Change-Id: I1d0e777c8e098f5a1d30aa5fa3090c8ce6b3dbee git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@263168 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 29 +++++ gcc/builtin-attrs.def | 2 + gcc/builtin-types.def | 6 + gcc/builtins.c | 60 ++++++++++ gcc/builtins.def | 22 ++++ gcc/c-family/ChangeLog | 9 ++ gcc/c-family/c-common.c | 164 ++++++++++++++++++++++++++++ gcc/c-family/c-cppbuiltin.c | 7 +- gcc/doc/cpp.texi | 4 + gcc/doc/extend.texi | 91 +++++++++++++++ gcc/doc/md.texi | 15 +++ gcc/doc/tm.texi | 31 ++++++ gcc/doc/tm.texi.in | 4 + gcc/target.def | 35 ++++++ gcc/targhooks.c | 32 ++++++ gcc/targhooks.h | 3 + gcc/testsuite/ChangeLog | 6 + gcc/testsuite/c-c++-common/spec-barrier-1.c | 38 +++++++ gcc/testsuite/c-c++-common/spec-barrier-2.c | 17 +++ gcc/testsuite/gcc.dg/spec-barrier-3.c | 13 +++ 20 files changed, 587 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/c-c++-common/spec-barrier-1.c create mode 100644 gcc/testsuite/c-c++-common/spec-barrier-2.c create mode 100644 gcc/testsuite/gcc.dg/spec-barrier-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76eb226..9c1bbc5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2018-07-31 Richard Earnshaw + + * builtin-types.def (BT_FN_PTR_PTR_VAR): New function type. + (BT_FN_I1_I1_VAR, BT_FN_I2_I2_VAR, BT_FN_I4_I4_VAR): Likewise. + (BT_FN_I8_I8_VAR, BT_FN_I16_I16_VAR): Likewise. + * builtin-attrs.def (ATTR_NOVOPS_NOTHROW_LEAF_LIST): New attribute + list. + * builtins.def (BUILT_IN_SPECULATION_SAFE_VALUE_N): New builtin. + (BUILT_IN_SPECULATION_SAFE_VALUE_PTR): New internal builtin. + (BUILT_IN_SPECULATION_SAFE_VALUE_1): Likewise. + (BUILT_IN_SPECULATION_SAFE_VALUE_2): Likewise. + (BUILT_IN_SPECULATION_SAFE_VALUE_4): Likewise. + (BUILT_IN_SPECULATION_SAFE_VALUE_8): Likewise. + (BUILT_IN_SPECULATION_SAFE_VALUE_16): Likewise. + * builtins.c (expand_speculation_safe_value): New function. + (expand_builtin): Call it. + * doc/cpp.texi: Document predefine __HAVE_SPECULATION_SAFE_VALUE. + * doc/extend.texi: Document __builtin_speculation_safe_value. + * doc/md.texi: Document "speculation_barrier" pattern. + * doc/tm.texi.in: Pull in TARGET_SPECULATION_SAFE_VALUE and + TARGET_HAVE_SPECULATION_SAFE_VALUE. + * doc/tm.texi: Regenerated. + * target.def (have_speculation_safe_value, speculation_safe_value): New + hooks. + * targhooks.c (default_have_speculation_safe_value): New function. + (default_speculation_safe_value): New function. + * targhooks.h (default_have_speculation_safe_value): Add prototype. + (default_speculation_safe_value): Add prototype. + 2017-06-02 Kyrylo Tkachov * config/aarch64/aarch64.c (aarch64_split_compare_and_swap): diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index 089817a..80edf76 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -119,6 +119,8 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL) DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_NOVOPS_NOTHROW_LEAF_LIST, ATTR_NOVOPS, \ + ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \ ATTR_NULL, ATTR_NOTHROW_LIST) DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LEAF_LIST, ATTR_CONST, \ diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 7fab9f8..69c455a 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -588,6 +588,12 @@ DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_LONG_VAR, BT_VOID, BT_LONG) DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_ULL_VAR, BT_VOID, BT_ULONGLONG) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_PTR_PTR_VAR, BT_PTR, BT_PTR) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I1_I1_VAR, BT_I1, BT_I1) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I2_I2_VAR, BT_I2, BT_I2) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I4_I4_VAR, BT_I4, BT_I4) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I8_I8_VAR, BT_I8, BT_I8) +DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I16_I16_VAR, BT_I16, BT_I16) DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR, BT_INT, BT_FILEPTR, BT_CONST_STRING) diff --git a/gcc/builtins.c b/gcc/builtins.c index d32a1d1..cb15cb2 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5608,6 +5608,55 @@ expand_stack_save (void) } +/* Expand a call to __builtin_speculation_safe_value_. MODE + represents the size of the first argument to that call, or VOIDmode + if the argument is a pointer. IGNORE will be true if the result + isn't used. */ +static rtx +expand_speculation_safe_value (machine_mode mode, tree exp, rtx target, + bool ignore) +{ + rtx val, failsafe; + unsigned nargs = call_expr_nargs (exp); + + tree arg0 = CALL_EXPR_ARG (exp, 0); + + if (mode == VOIDmode) + { + mode = TYPE_MODE (TREE_TYPE (arg0)); + gcc_assert (GET_MODE_CLASS (mode) == MODE_INT); + } + + val = expand_expr (arg0, NULL_RTX, mode, EXPAND_NORMAL); + + /* An optional second argument can be used as a failsafe value on + some machines. If it isn't present, then the failsafe value is + assumed to be 0. */ + if (nargs > 1) + { + tree arg1 = CALL_EXPR_ARG (exp, 1); + failsafe = expand_expr (arg1, NULL_RTX, mode, EXPAND_NORMAL); + } + else + failsafe = const0_rtx; + + /* If the result isn't used, the behavior is undefined. It would be + nice to emit a warning here, but path splitting means this might + happen with legitimate code. So simply drop the builtin + expansion in that case; we've handled any side-effects above. */ + if (ignore) + return const0_rtx; + + /* If we don't have a suitable target, create one to hold the result. */ + if (target == NULL || GET_MODE (target) != mode) + target = gen_reg_rtx (mode); + + if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode) + val = convert_modes (mode, VOIDmode, val, false); + + return targetm.speculation_safe_value (mode, target, val, failsafe); +} + /* Expand an expression EXP that calls a built-in function, with result going to TARGET if that's convenient (and in mode MODE if that's convenient). @@ -6702,6 +6751,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, folding. */ break; + case BUILT_IN_SPECULATION_SAFE_VALUE_PTR: + return expand_speculation_safe_value (VOIDmode, exp, target, ignore); + + case BUILT_IN_SPECULATION_SAFE_VALUE_1: + case BUILT_IN_SPECULATION_SAFE_VALUE_2: + case BUILT_IN_SPECULATION_SAFE_VALUE_4: + case BUILT_IN_SPECULATION_SAFE_VALUE_8: + case BUILT_IN_SPECULATION_SAFE_VALUE_16: + mode = get_builtin_sync_mode (fcode - BUILT_IN_SPECULATION_SAFE_VALUE_1); + return expand_speculation_safe_value (mode, exp, target, ignore); + default: /* just do library call, if unknown builtin */ break; } diff --git a/gcc/builtins.def b/gcc/builtins.def index 10cbdbe..157ee06 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -916,6 +916,28 @@ DEF_BUILTIN (BUILT_IN_EMUTLS_REGISTER_COMMON, true, true, true, ATTR_NOTHROW_LEAF_LIST, false, !targetm.have_tls) +/* Suppressing speculation. Users are expected to use the first (N) + variant, which will be translated internally into one of the other + types. */ + +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_N, "speculation_safe_value", + BT_FN_VOID_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST) + +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_PTR, + "speculation_safe_value_ptr", BT_FN_PTR_PTR_VAR, + ATTR_NOVOPS_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_1, "speculation_safe_value_1", + BT_FN_I1_I1_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_2, "speculation_safe_value_2", + BT_FN_I2_I2_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_4, "speculation_safe_value_4", + BT_FN_I4_I4_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_8, "speculation_safe_value_8", + BT_FN_I8_I8_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_16, + "speculation_safe_value_16", BT_FN_I16_I16_VAR, + ATTR_NOVOPS_NOTHROW_LEAF_LIST) + /* Exception support. */ DEF_BUILTIN_STUB (BUILT_IN_UNWIND_RESUME, "__builtin_unwind_resume") DEF_BUILTIN_STUB (BUILT_IN_CXA_END_CLEANUP, "__builtin_cxa_end_cleanup") diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bdd4e9e..2b19e8f 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2018-07-31 Richard Earnshaw + + * c-common.c (speculation_safe_resolve_call): New function. + (speculation_safe_resolve_params): New function. + (speculation_safe_resolve_return): New function. + (resolve_overloaded_builtin): Handle __builtin_speculation_safe_value. + * c-cppbuiltin.c (c_cpp_builtins): Add pre-define for + __HAVE_SPECULATION_SAFE_VALUE. + 2017-01-10 Martin Liska Backport from mainline diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index b2b36b5..1a7c375 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -10787,6 +10787,122 @@ builtin_type_for_size (int size, bool unsignedp) return type ? type : error_mark_node; } +/* Work out the size of the first argument of a call to + __builtin_speculation_safe_value. Only pointers and integral types + are permitted. Return -1 if the argument type is not supported or + the size is too large; 0 if the argument type is a pointer or the + size if it is integral. */ +static enum built_in_function +speculation_safe_value_resolve_call (tree function, vec *params) +{ + /* Type of the argument. */ + tree type; + int size; + + if (vec_safe_is_empty (params)) + { + error ("too few arguments to function %qE", function); + return BUILT_IN_NONE; + } + + type = TREE_TYPE ((*params)[0]); + if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ()) + { + /* Force array-to-pointer decay for C++. */ + (*params)[0] = default_conversion ((*params)[0]); + type = TREE_TYPE ((*params)[0]); + } + + if (POINTER_TYPE_P (type)) + return BUILT_IN_SPECULATION_SAFE_VALUE_PTR; + + if (!INTEGRAL_TYPE_P (type)) + goto incompatible; + + if (!COMPLETE_TYPE_P (type)) + goto incompatible; + + size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16) + return ((enum built_in_function) + ((int) BUILT_IN_SPECULATION_SAFE_VALUE_1 + exact_log2 (size))); + + incompatible: + /* Issue the diagnostic only if the argument is valid, otherwise + it would be redundant at best and could be misleading. */ + if (type != error_mark_node) + error ("operand type %qT is incompatible with argument %d of %qE", + type, 1, function); + + return BUILT_IN_NONE; +} + +/* Validate and coerce PARAMS, the arguments to ORIG_FUNCTION to fit + the prototype for FUNCTION. The first argument is mandatory, a second + argument, if present, must be type compatible with the first. */ +static bool +speculation_safe_value_resolve_params (location_t loc, tree orig_function, + vec *params) +{ + tree val; + + if (params->length () == 0) + { + error_at (loc, "too few arguments to function %qE", orig_function); + return false; + } + + else if (params->length () > 2) + { + error_at (loc, "too many arguments to function %qE", orig_function); + return false; + } + + val = (*params)[0]; + if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE) + val = default_conversion (val); + if (!(TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE + || TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE)) + { + error_at (loc, + "expecting argument of type pointer or of type integer " + "for argument 1"); + return false; + } + (*params)[0] = val; + + if (params->length () == 2) + { + tree val2 = (*params)[1]; + if (TREE_CODE (TREE_TYPE (val2)) == ARRAY_TYPE) + val2 = default_conversion (val2); + if (!(TREE_TYPE (val) == TREE_TYPE (val2) + || useless_type_conversion_p (TREE_TYPE (val), TREE_TYPE (val2)))) + { + error_at (loc, "both arguments must be compatible"); + return false; + } + (*params)[1] = val2; + } + + return true; +} + +/* Cast the result of the builtin back to the type of the first argument, + preserving any qualifiers that it might have. */ +static tree +speculation_safe_value_resolve_return (tree first_param, tree result) +{ + tree ptype = TREE_TYPE (first_param); + tree rtype = TREE_TYPE (result); + ptype = TYPE_MAIN_VARIANT (ptype); + + if (tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype))) + return convert (ptype, result); + + return result; +} + /* A helper function for resolve_overloaded_builtin in resolving the overloaded __sync_ builtins. Returns a positive power of 2 if the first operand of PARAMS is a pointer to a supported data type. @@ -11419,6 +11535,54 @@ resolve_overloaded_builtin (location_t loc, tree function, /* Handle BUILT_IN_NORMAL here. */ switch (orig_code) { + case BUILT_IN_SPECULATION_SAFE_VALUE_N: + { + tree new_function, first_param, result; + enum built_in_function fncode + = speculation_safe_value_resolve_call (function, params);; + + first_param = (*params)[0]; + if (fncode == BUILT_IN_NONE + || !speculation_safe_value_resolve_params (loc, function, params)) + return error_mark_node; + + if (targetm.have_speculation_safe_value (true)) + { + new_function = builtin_decl_explicit (fncode); + result = build_function_call_vec (loc, vNULL, new_function, params, + NULL); + + if (result == error_mark_node) + return result; + + return speculation_safe_value_resolve_return (first_param, result); + } + else + { + /* This target doesn't have, or doesn't need, active mitigation + against incorrect speculative execution. Simply return the + first parameter to the builtin. */ + if (!targetm.have_speculation_safe_value (false)) + /* The user has invoked __builtin_speculation_safe_value + even though __HAVE_SPECULATION_SAFE_VALUE is not + defined: emit a warning. */ + warning_at (input_location, 0, + "this target does not define a speculation barrier; " + "your program will still execute correctly, " + "but incorrect speculation may not be be " + "restricted"); + + /* If the optional second argument is present, handle any side + effects now. */ + if (params->length () == 2 + && TREE_SIDE_EFFECTS ((*params)[1])) + return build2 (COMPOUND_EXPR, TREE_TYPE (first_param), + (*params)[1], first_param); + + return first_param; + } + } + case BUILT_IN_ATOMIC_EXCHANGE: case BUILT_IN_ATOMIC_COMPARE_EXCHANGE: case BUILT_IN_ATOMIC_LOAD: diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 3d4587e..a560fea 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1202,7 +1202,12 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__WCHAR_UNSIGNED__"); cpp_atomic_builtins (pfile); - + + /* Show support for __builtin_speculation_safe_value () if the target + has been updated to fully support it. */ + if (targetm.have_speculation_safe_value (false)) + cpp_define (pfile, "__HAVE_SPECULATION_SAFE_VALUE"); + #ifdef DWARF2_UNWIND_INFO if (dwarf2out_do_cfi_asm ()) cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM"); diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index 9f914b2..40e7be7 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -2381,6 +2381,10 @@ If GCC cannot determine the current date, it will emit a warning message These macros are defined when the target processor supports atomic compare and swap operations on operands 1, 2, 4, 8 or 16 bytes in length, respectively. +@item __HAVE_SPECULATION_SAFE_VALUE +This macro is defined with the value 1 to show that this version of GCC +supports @code{__builtin_speculation_safe_value}. + @item __GCC_HAVE_DWARF2_CFI_ASM This macro is defined when the compiler is emitting DWARF CFI directives to the assembler. When this is defined, it is possible to emit those same diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 0c91d85..7bb173f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -10228,6 +10228,7 @@ in the Cilk Plus language manual which can be found at @findex __builtin_powi @findex __builtin_powif @findex __builtin_powil +@findex __builtin_speculation_safe_value @findex _Exit @findex _exit @findex abort @@ -10854,6 +10855,96 @@ an extension. @xref{Variable Length}, for details. @end deftypefn +@deftypefn {Built-in Function} @var{type} __builtin_speculation_safe_value (@var{type} val, @var{type} failval) + +This built-in function can be used to help mitigate against unsafe +speculative execution. @var{type} may be any integral type or any +pointer type. + +@enumerate +@item +If the CPU is not speculatively executing the code, then @var{val} +is returned. +@item +If the CPU is executing speculatively then either: +@itemize +@item +The function may cause execution to pause until it is known that the +code is no-longer being executed speculatively (in which case +@var{val} can be returned, as above); or +@item +The function may use target-dependent speculation tracking state to cause +@var{failval} to be returned when it is known that speculative +execution has incorrectly predicted a conditional branch operation. +@end itemize +@end enumerate + +The second argument, @var{failval}, is optional and defaults to zero +if omitted. + +GCC defines the preprocessor macro +@code{__HAVE_BUILTIN_SPECULATION_SAFE_VALUE} for targets that have been +updated to support this builtin. + +The built-in function can be used where a variable appears to be used in a +safe way, but the CPU, due to speculative execution may temporarily ignore +the bounds checks. Consider, for example, the following function: + +@smallexample +int array[500]; +int f (unsigned untrusted_index) +@{ + if (untrusted_index < 500) + return array[untrusted_index]; + return 0; +@} +@end smallexample + +If the function is called repeatedly with @code{untrusted_index} less +than the limit of 500, then a branch predictor will learn that the +block of code that returns a value stored in @code{array} will be +executed. If the function is subsequently called with an +out-of-range value it will still try to execute that block of code +first until the CPU determines that the prediction was incorrect +(the CPU will unwind any incorrect operations at that point). +However, depending on how the result of the function is used, it might be +possible to leave traces in the cache that can reveal what was stored +at the out-of-bounds location. The built-in function can be used to +provide some protection against leaking data in this way by changing +the code to: + +@smallexample +int array[500]; +int f (unsigned untrusted_index) +@{ + if (untrusted_index < 500) + return array[__builtin_speculation_safe_value (untrusted_index)]; + return 0; +@} +@end smallexample + +The built-in function will either cause execution to stall until the +conditional branch has been fully resolved, or it may permit +speculative execution to continue, but using 0 instead of +@code{untrusted_value} if that exceeds the limit. + +If accessing any memory location is potentially unsafe when speculative +execution is incorrect, then the code can be rewritten as + +@smallexample +int array[500]; +int f (unsigned untrusted_index) +@{ + if (untrusted_index < 500) + return *__builtin_speculation_safe_value (&array[untrusted_index], NULL); + return 0; +@} +@end smallexample + +which will cause a @code{NULL} pointer to be used for the unsafe case. + +@end deftypefn + @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2}) You can use the built-in function @code{__builtin_types_compatible_p} to diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index d12c7b1..45406c9 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -6645,6 +6645,21 @@ should be defined to an instruction that orders both loads and stores before the instruction with respect to loads and stores after the instruction. This pattern has no operands. +@cindex @code{speculation_barrier} instruction pattern +@item @samp{speculation_barrier} +If the target can support speculative execution, then this pattern should +be defined to an instruction that will block subsequent execution until +any prior speculation conditions has been resolved. The pattern must also +ensure that the compiler cannot move memory operations past the barrier, +so it needs to be an UNSPEC_VOLATILE pattern. The pattern has no +operands. + +If this pattern is not defined then the default expansion of +@code{__builtin_speculation_safe_value} will emit a warning. You can +suppress this warning by defining this pattern with a final condition +of @code{0} (zero), which tells the compiler that a speculation +barrier is not needed for this target. + @cindex @code{sync_compare_and_swap@var{mode}} instruction pattern @item @samp{sync_compare_and_swap@var{mode}} This pattern, if defined, emits code for an atomic compare-and-swap diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 745910f..e8166b8 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11678,3 +11678,34 @@ All and all it does not take long to convert ports that the maintainer is familiar with. @end defmac + +@deftypefn {Target Hook} bool TARGET_HAVE_SPECULATION_SAFE_VALUE (bool @var{active}) +This hook is used to determine the level of target support for + @code{__builtin_speculation_safe_value}. If called with an argument + of false, it returns true if the target has been modified to support + this builtin. If called with an argument of true, it returns true + if the target requires active mitigation execution might be speculative. + + The default implementation returns false if the target does not define + a pattern named @code{speculation_barrier}. Else it returns true + for the first case and whether the pattern is enabled for the current + compilation for the second case. +@end deftypefn + +@deftypefn {Target Hook} rtx TARGET_SPECULATION_SAFE_VALUE (machine_mode @var{mode}, rtx @var{result}, rtx @var{val}, rtx @var{failval}) +This target hook can be used to generate a target-specific code + sequence that implements the @code{__builtin_speculation_safe_value} + built-in function. The function must always return @var{val} in + @var{result} in mode @var{mode} when the cpu is not executing + speculatively, but must never return that when speculating until it + is known that the speculation will not be unwound. The hook supports + two primary mechanisms for implementing the requirements. The first + is to emit a speculation barrier which forces the processor to wait + until all prior speculative operations have been resolved; the second + is to use a target-specific mechanism that can track the speculation + state and to return @var{failval} if it can determine that + speculation must be unwound at a later time. + + The default implementation simply copies @var{val} to @var{result} and + emits a @code{speculation_barrier} instruction if that is defined. +@end deftypefn diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f31c763..a7f5790 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -8262,3 +8262,7 @@ All and all it does not take long to convert ports that the maintainer is familiar with. @end defmac + +@hook TARGET_HAVE_SPECULATION_SAFE_VALUE + +@hook TARGET_SPECULATION_SAFE_VALUE diff --git a/gcc/target.def b/gcc/target.def index 20f2b32..a4f21ad 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3942,6 +3942,41 @@ normally defined in @file{libgcc2.c}.", default_external_stack_protect_fail) DEFHOOK +(have_speculation_safe_value, +"This hook is used to determine the level of target support for\n\ + @code{__builtin_speculation_safe_value}. If called with an argument\n\ + of false, it returns true if the target has been modified to support\n\ + this builtin. If called with an argument of true, it returns true\n\ + if the target requires active mitigation execution might be speculative.\n\ + \n\ + The default implementation returns false if the target does not define\n\ + a pattern named @code{speculation_barrier}. Else it returns true\n\ + for the first case and whether the pattern is enabled for the current\n\ + compilation for the second case.", +bool, (bool active), default_have_speculation_safe_value) + +DEFHOOK +(speculation_safe_value, +"This target hook can be used to generate a target-specific code\n\ + sequence that implements the @code{__builtin_speculation_safe_value}\n\ + built-in function. The function must always return @var{val} in\n\ + @var{result} in mode @var{mode} when the cpu is not executing\n\ + speculatively, but must never return that when speculating until it\n\ + is known that the speculation will not be unwound. The hook supports\n\ + two primary mechanisms for implementing the requirements. The first\n\ + is to emit a speculation barrier which forces the processor to wait\n\ + until all prior speculative operations have been resolved; the second\n\ + is to use a target-specific mechanism that can track the speculation\n\ + state and to return @var{failval} if it can determine that\n\ + speculation must be unwound at a later time.\n\ + \n\ + The default implementation simply copies @var{val} to @var{result} and\n\ + emits a @code{speculation_barrier} instruction if that is defined.", +rtx, (machine_mode mode, rtx result, rtx val, rtx failval), + default_speculation_safe_value) + + +DEFHOOK (can_use_doloop_p, "Return true if it is possible to use low-overhead loops (@code{doloop_end}\n\ and @code{doloop_begin}) for a particular loop. @var{iterations} gives the\n\ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 6b4601b..d9db06f 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1965,4 +1965,36 @@ default_optab_supported_p (int, machine_mode, machine_mode, optimization_type) return true; } +/* Default implementation of TARGET_HAVE_SPECULATION_SAFE_VALUE. */ +bool +default_have_speculation_safe_value (bool active) +{ +#ifdef HAVE_speculation_barrier + return active ? HAVE_speculation_barrier : true; +#else + return false; +#endif +} + +/* Default implementation of the speculation-safe-load builtin. This + implementation simply copies val to result and generates a + speculation_barrier insn, if such a pattern is defined. */ +rtx +default_speculation_safe_value (machine_mode mode ATTRIBUTE_UNUSED, + rtx result, rtx val, + rtx failval ATTRIBUTE_UNUSED) +{ + emit_move_insn (result, val); + +#ifdef HAVE_speculation_barrier + /* Assume the target knows what it is doing: if it defines a + speculation barrier, but it is not enabled, then assume that one + isn't needed. */ + if (HAVE_speculation_barrier) + emit_insn (gen_speculation_barrier ()); +#endif + + return result; +} + #include "gt-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 7687c39..01501b2 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -254,4 +254,7 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE extern bool default_optab_supported_p (int, machine_mode, machine_mode, optimization_type); +extern bool default_have_speculation_safe_value (bool); +extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx); + #endif /* GCC_TARGHOOKS_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f3714bb..9d3e242 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-07-31 Richard Earnshaw + + * c-c++-common/spec-barrier-1.c: New test. + * c-c++-common/spec-barrier-2.c: New test. + * gcc.dg/spec-barrier-3.c: New test. + 2017-06-02 Kyrylo Tkachov * gcc.target/aarch64/atomic_cmp_exchange_zero_strong_1.c: New test. diff --git a/gcc/testsuite/c-c++-common/spec-barrier-1.c b/gcc/testsuite/c-c++-common/spec-barrier-1.c new file mode 100644 index 0000000..e4b44f2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/spec-barrier-1.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +/* Test that __builtin_speculation_safe_value returns the correct value. */ +/* This test will cause an unfiltered warning to be emitted on targets + that have not implemented support for speculative execution + barriers. They should fix that rather than disabling this + test. */ +char a = 1; +short b = 2; +int c = 3; +long d = 4; +long long e = 5; +int *f = (int*) &c; +#ifdef __SIZEOF_INT128__ +__int128 g = 9; +#endif + +int main () +{ + if (__builtin_speculation_safe_value (a) != 1) + __builtin_abort (); + if (__builtin_speculation_safe_value (b) != 2) + __builtin_abort (); + if (__builtin_speculation_safe_value (c) != 3) + __builtin_abort (); + if (__builtin_speculation_safe_value (d) != 4) + __builtin_abort (); + if (__builtin_speculation_safe_value (e) != 5) + __builtin_abort (); + if (__builtin_speculation_safe_value (f) != &c) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + if (__builtin_speculation_safe_value (g) != 9) + __builtin_abort (); +#endif + return 0; +} diff --git a/gcc/testsuite/c-c++-common/spec-barrier-2.c b/gcc/testsuite/c-c++-common/spec-barrier-2.c new file mode 100644 index 0000000..b09567e --- /dev/null +++ b/gcc/testsuite/c-c++-common/spec-barrier-2.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +/* Even on targets that don't need the optional failval parameter, + side-effects on the operand should still be calculated. */ + +int x = 3; +volatile int y = 9; + +int main () +{ + int z = __builtin_speculation_safe_value (x, y++); + if (z != 3 || y != 10) + __builtin_abort (); + return 0; +} + +/* { dg-prune-output "this target does not define a speculation barrier;" } */ diff --git a/gcc/testsuite/gcc.dg/spec-barrier-3.c b/gcc/testsuite/gcc.dg/spec-barrier-3.c new file mode 100644 index 0000000..7376f3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/spec-barrier-3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-Wpedantic" } */ + +/* __builtin_speculation_safe_value returns a value with the same type + as its first argument. There should be a warning if that isn't + type-compatible with the use. */ +int * +f (int x) +{ + return __builtin_speculation_safe_value (x); /* { dg-warning "return makes pointer from integer without a cast" } */ +} + +/* { dg-prune-output "this target does not define a speculation barrier;" } */ -- 2.7.4 From 61e24354d3a2a9153f2a730be9d33dc9f3278cec Mon Sep 17 00:00:00 2001 From: rearnsha Date: Tue, 31 Jul 2018 17:35:41 +0000 Subject: [PATCH 15/16] Arm - add speculation_barrier pattern This patch defines a speculation barrier for AArch32. * config/arm/unspecs.md (unspecv): Add VUNSPEC_SPECULATION_BARRIER. * config/arm/arm.md (speculation_barrier): New expand. (speculation_barrier_insn): New pattern. (backported be626997e0edc646c17e9e1eadabf97152e82eeb) git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@263169 138bc75d-0d04-0410-961f-82ee72b054a4 Change-Id: I5f587e22dd1a92440a6a208e2baca189427557da --- gcc/ChangeLog | 6 ++++++ gcc/config/arm/arm.md | 21 +++++++++++++++++++++ gcc/config/arm/unspecs.md | 1 + 3 files changed, 28 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c1bbc5..ab2e761 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2018-07-31 Richard Earnshaw + * config/arm/unspecs.md (unspecv): Add VUNSPEC_SPECULATION_BARRIER. + * config/arm/arm.md (speculation_barrier): New expand. + (speculation_barrier_insn): New pattern. + +2018-07-31 Richard Earnshaw + * builtin-types.def (BT_FN_PTR_PTR_VAR): New function type. (BT_FN_I1_I1_VAR, BT_FN_I2_I2_VAR, BT_FN_I4_I4_VAR): Likewise. (BT_FN_I8_I8_VAR, BT_FN_I16_I16_VAR): Likewise. diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 5cc6997..ffdd6c2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -11921,6 +11921,27 @@ DONE; }) +(define_expand "speculation_barrier" + [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)] + "TARGET_EITHER" + " + /* Don't emit anything for Thumb1 and suppress the warning from the + generic expansion. */ + if (!TARGET_32BIT) + DONE; + " +) + +;; Generate a hard speculation barrier when we have not enabled speculation +;; tracking. +(define_insn "*speculation_barrier_insn" + [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)] + "TARGET_32BIT" + "isb\;dsb\\tsy" + [(set_attr "type" "block") + (set_attr "length" "8")] +) + ;; Vector bits common to IWMMXT and Neon (include "vec-common.md") ;; Load the Intel Wireless Multimedia Extension patterns diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 1aa39e8..db96cf1 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -150,6 +150,7 @@ VUNSPEC_GET_FPSCR ; Represent fetch of FPSCR content. VUNSPEC_SET_FPSCR ; Represent assign of FPSCR content. VUNSPEC_PROBE_STACK_RANGE ; Represent stack range probing. + VUNSPEC_SPECULATION_BARRIER ; Represents an unconditional speculation barrier. ]) ;; Enumerators for NEON unspecs. -- 2.7.4 From 81f53356576efc2be3ba0748551ac8b282bb6491 Mon Sep 17 00:00:00 2001 From: rearnsha Date: Tue, 31 Jul 2018 17:35:50 +0000 Subject: [PATCH 16/16] AArch64 - add speculation barrier Similar to Arm, this adds an unconditional speculation barrier for AArch64. * config/aarch64.md (unspecv): Add UNSPECV_SPECULAION_BARRIER. (speculation_barrier): New insn. (backported f9d2906f0b6803c42b2200da5e32e331930fc306) git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@263170 138bc75d-0d04-0410-961f-82ee72b054a4 Change-Id: Ic9a1826c24f8597033716cec3d02de12fdb57dba --- gcc/ChangeLog | 5 +++++ gcc/config/aarch64/aarch64.md | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab2e761..ec6ae81 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2018-07-31 Richard Earnshaw + * config/aarch64.md (unspecv): Add UNSPECV_SPECULAION_BARRIER. + (speculation_barrier): New insn. + +2018-07-31 Richard Earnshaw + * config/arm/unspecs.md (unspecv): Add VUNSPEC_SPECULATION_BARRIER. * config/arm/arm.md (speculation_barrier): New expand. (speculation_barrier_insn): New pattern. diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 6fc7979..6a03262 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -144,6 +144,7 @@ UNSPECV_SET_FPSR ; Represent assign of FPSR content. UNSPECV_BLOCKAGE ; Represent a blockage UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing. + UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier. ] ) @@ -5405,6 +5406,15 @@ DONE; }) +;; Hard speculation barrier. +(define_insn "speculation_barrier" + [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)] + "" + "isb\;dsb\\tsy" + [(set_attr "length" "8") + (set_attr "type" "block")] +) + ;; AdvSIMD Stuff (include "aarch64-simd.md") -- 2.7.4