From de6ab1bcbc55bab9b8cd46102a9f02dea5e2af12 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 4 Nov 2024 14:29:27 +0800 Subject: [PATCH 1/6] [RISCV] Remove unnecessary +zfh from strided VP load/store tests. NFC --- .../RISCV/rvv/fixed-vectors-strided-vpload.ll | 8 ++++---- .../RISCV/rvv/fixed-vectors-strided-vpstore.ll | 4 ++-- llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll | 16 ++++++++-------- llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll index 849f98c26f45..fa857565031b 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll @@ -1,14 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-NO-OPT -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-NO-OPT diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpstore.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpstore.ll index 35f123f1157f..ddd86c308202 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpstore.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpstore.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64 diff --git a/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll b/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll index 87ff1859a4d2..f50c4c9a7bf4 100644 --- a/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll +++ b/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll @@ -1,26 +1,26 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-ZVFH,CHECK-OPT-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-ZVFH,CHECK-OPT-RV64 -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-NO-OPT,CHECK-NO-OPT-ZVFH,CHECK-NO-OPT-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-NO-OPT,CHECK-NO-OPT-ZVFH,CHECK-NO-OPT-RV64 -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-ZVFHMIN,CHECK-OPT-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-ZVFHMIN,CHECK-OPT-RV64 -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-NO-OPT,CHECK-NO-OPT-ZVFHMIN,CHECK-NO-OPT-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-NO-OPT,CHECK-NO-OPT-ZVFHMIN,CHECK-NO-OPT-RV64 diff --git a/llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll b/llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll index abdf9ab09bb9..ecbd86581980 100644 --- a/llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll +++ b/llvm/test/CodeGen/RISCV/rvv/strided-vpstore.ll @@ -1,14 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s | FileCheck %s \ ; RUN: -check-prefixes=CHECK,CHECK-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfh,+zvfbfmin \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s | FileCheck %s \ ; RUN: -check-prefixes=CHECK,CHECK-RV64 -; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin \ +; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s | FileCheck %s \ ; RUN: -check-prefixes=CHECK,CHECK-RV32 -; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+zfh,+v,+zvfhmin,+zvfbfmin \ +; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s | FileCheck %s \ ; RUN: -check-prefixes=CHECK,CHECK-RV64 From 8bc04e4c93cb681249c258bc0a1b1aa1b3fe71f4 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 4 Nov 2024 14:31:25 +0800 Subject: [PATCH 2/6] [RISCV] Remove completed TODO in VP strided load test. NFC This was done in #101329 --- llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll index fa857565031b..14cc3edffb8c 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-vpload.ll @@ -633,7 +633,6 @@ define <33 x double> @strided_load_v33f64(ptr %ptr, i64 %stride, <33 x i1> %mask declare <33 x double> @llvm.experimental.vp.strided.load.v33f64.p0.i64(ptr, i64, <33 x i1>, i32) -; TODO: Use accurate evl. ; Test unmasked integer zero strided define <4 x i8> @zero_strided_unmasked_vpload_4i8_i8(ptr %ptr) { ; CHECK-OPT-LABEL: zero_strided_unmasked_vpload_4i8_i8: @@ -652,7 +651,6 @@ define <4 x i8> @zero_strided_unmasked_vpload_4i8_i8(ptr %ptr) { ret <4 x i8> %load } -; TODO: Use accurate evl. ; Test unmasked float zero strided define <4 x half> @zero_strided_unmasked_vpload_4f16(ptr %ptr) { ; CHECK-OPT-LABEL: zero_strided_unmasked_vpload_4f16: From f8535fd8b4a986cafa2e77e0f880dbd4e10300d8 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 4 Nov 2024 15:29:37 +0800 Subject: [PATCH 3/6] [RISCV] Remove unused check prefixes from VP strided load test. NFC --- llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll b/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll index f50c4c9a7bf4..0e76518f67e1 100644 --- a/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll +++ b/llvm/test/CodeGen/RISCV/rvv/strided-vpload.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ -; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-ZVFH,CHECK-OPT-RV32 +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-RV32 ; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfh,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ -; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-ZVFH,CHECK-OPT-RV64 +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-RV64 ; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfh,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-NO-OPT,CHECK-NO-OPT-ZVFH,CHECK-NO-OPT-RV32 @@ -13,10 +13,10 @@ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-NO-OPT,CHECK-NO-OPT-ZVFH,CHECK-NO-OPT-RV64 ; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ -; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-ZVFHMIN,CHECK-OPT-RV32 +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-OPT,CHECK-OPT-RV32 ; RUN: llc -mtriple=riscv64 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin,+optimized-zero-stride-load \ ; RUN: -verify-machineinstrs < %s \ -; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-ZVFHMIN,CHECK-OPT-RV64 +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV64,CHECK-OPT,CHECK-OPT-RV64 ; RUN: llc -mtriple=riscv32 -mattr=+m,+d,+v,+zvfhmin,+zvfbfmin \ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-RV32,CHECK-NO-OPT,CHECK-NO-OPT-ZVFHMIN,CHECK-NO-OPT-RV32 @@ -995,6 +995,3 @@ define @zero_strided_vadd_nxv1p0( %v, ptr % %load = call @llvm.experimental.vp.strided.load.nxv1p0.p0.i32(ptr %ptr, i32 0, splat (i1 true), i32 %vscale) ret %load } -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; CHECK-OPT-ZVFH: {{.*}} -; CHECK-OPT-ZVFHMIN: {{.*}} From 3dd1d888fb18b40859504e207e57abdc6c43d838 Mon Sep 17 00:00:00 2001 From: Justin Stitt Date: Sun, 3 Nov 2024 23:57:47 -0800 Subject: [PATCH 4/6] [Clang] Implement labelled type filtering for overflow/truncation sanitizers w/ SSCLs (#107332) [Related RFC](https://discourse.llvm.org/t/rfc-support-globpattern-add-operator-to-invert-matches/80683/5?u=justinstitt) ### Summary Implement type-based filtering via [Sanitizer Special Case Lists](https://clang.llvm.org/docs/SanitizerSpecialCaseList.html) for the arithmetic overflow and truncation sanitizers. Currently, using the `type:` prefix with these sanitizers does nothing. I've hooked up the SSCL parsing with Clang codegen so that we don't emit the overflow/truncation checks if the arithmetic contains an ignored type. ### Usefulness You can craft ignorelists that ignore specific types that are expected to overflow or wrap-around. For example, to ignore `my_type` from `unsigned-integer-overflow` instrumentation: ```bash $ cat ignorelist.txt [unsigned-integer-overflow] type:my_type=no_sanitize $ cat foo.c typedef unsigned long my_type; void foo() { my_type a = ULONG_MAX; ++a; } $ clang foo.c -fsanitize=unsigned-integer-overflow -fsanitize-ignorelist=ignorelist.txt ; ./a.out // --> no sanitizer error ``` If a type is functionally intended to overflow, like [refcount_t](https://kernsec.org/wiki/index.php/Kernel_Protections/refcount_t) and its associated APIs in the Linux kernel, then this type filtering would prove useful for reducing sanitizer noise. Currently, the Linux kernel dealt with this by [littering](https://elixir.bootlin.com/linux/v6.10.8/source/include/linux/refcount.h#L139 ) `__attribute__((no_sanitize("signed-integer-overflow")))` annotations on all the `refcount_t` APIs. I think this serves as an example of how a codebase could be made cleaner. We could make custom types that are filtered out in an ignorelist, allowing for types to be more expressive -- without the need for annotations. This accomplishes a similar goal to https://github.com/llvm/llvm-project/pull/86618. Yet another use case for this type filtering is whitelisting. We could ignore _all_ types, save a few. ```bash $ cat ignorelist.txt [implicit-signed-integer-truncation] type:*=no_sanitize # ignore literally all types type:short=sanitize # except `short` $ cat bar.c // compile with -fsanitize=implicit-signed-integer-truncation void bar(int toobig) { char a = toobig; // not instrumented short b = toobig; // instrumented } ``` ### Other ways to accomplish the goal of sanitizer allowlisting/whitelisting * ignore list SSCL type support (this PR that you're reading) * [my sanitize-allowlist branch](https://github.com/llvm/llvm-project/compare/main...JustinStitt:llvm-project:sanitize-allowlist) - this just implements a sibling flag `-fsanitize-allowlist=`, removing some of the double negative logic present with `skip`/`ignore` when trying to whitelist something. * [Glob Negation](https://discourse.llvm.org/t/rfc-support-globpattern-add-operator-to-invert-matches/80683) - Implement a negation operator to the GlobPattern class so the ignorelist query can use them to simulate allowlisting Please let me know which of the three options we like best. They are not necessarily mutually exclusive. Here's [another related PR](https://github.com/llvm/llvm-project/pull/86618) which implements a `wraps` attribute. This can accomplish a similar goal to this PR but requires in-source changes to codebases and also covers a wider variety of integer definedness problems. ### CCs @kees @vitalybuka @bwendling --------- Signed-off-by: Justin Stitt --- clang/docs/ReleaseNotes.rst | 8 ++ clang/docs/SanitizerSpecialCaseList.rst | 61 +++++++++++- clang/include/clang/AST/ASTContext.h | 3 + clang/lib/AST/ASTContext.cpp | 9 ++ clang/lib/CodeGen/CGExprScalar.cpp | 36 ++++++- .../ubsan-type-ignorelist-category-2.test | 58 +++++++++++ .../ubsan-type-ignorelist-category.test | 98 +++++++++++++++++++ 7 files changed, 266 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGen/ubsan-type-ignorelist-category-2.test create mode 100644 clang/test/CodeGen/ubsan-type-ignorelist-category.test diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1372e49dfac0..a8e2e5c1e045 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -871,6 +871,14 @@ Sanitizers This new flag should allow those projects to enable integer sanitizers with less noise. +- Arithmetic overflow sanitizers ``-fsanitize=signed-integer-overflow`` and + ``-fsanitize=unsigned-integer-overflow`` as well as the implicit integer + truncation sanitizers ``-fsanitize=implicit-signed-integer-truncation`` and + ``-fsanitize=implicit-unsigned-integer-truncation`` now properly support the + "type" prefix within `Sanitizer Special Case Lists (SSCL) + `_. See that link + for examples. + Python Binding Changes ---------------------- - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``. diff --git a/clang/docs/SanitizerSpecialCaseList.rst b/clang/docs/SanitizerSpecialCaseList.rst index c7fb0fa3f8a8..96a7b2fba4ae 100644 --- a/clang/docs/SanitizerSpecialCaseList.rst +++ b/clang/docs/SanitizerSpecialCaseList.rst @@ -15,9 +15,9 @@ file at compile-time. Goal and usage ============== -Users of sanitizer tools, such as :doc:`AddressSanitizer`, :doc:`ThreadSanitizer` -or :doc:`MemorySanitizer` may want to disable or alter some checks for -certain source-level entities to: +Users of sanitizer tools, such as :doc:`AddressSanitizer`, +:doc:`ThreadSanitizer`, :doc:`MemorySanitizer` or :doc:`UndefinedBehaviorSanitizer` +may want to disable or alter some checks for certain source-level entities to: * speedup hot function, which is known to be correct; * ignore a function that does some low-level magic (e.g. walks through the @@ -48,6 +48,61 @@ Example $ clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out # No error report here. +Usage with UndefinedBehaviorSanitizer +===================================== + +The arithmetic overflow sanitizers ``unsigned-integer-overflow`` and +``signed-integer-overflow`` as well as the implicit integer truncation +sanitizers ``implicit-signed-integer-truncation`` and +``implicit-unsigned-integer-truncation`` support the ability to adjust +instrumentation based on type. + +By default, supported sanitizers will have their instrumentation disabled for +types specified within an ignorelist. + +.. code-block:: bash + + $ cat foo.c + void foo() { + int a = 2147483647; // INT_MAX + ++a; // Normally, an overflow with -fsanitize=signed-integer-overflow + } + $ cat ignorelist.txt + [signed-integer-overflow] + type:int + $ clang -fsanitize=signed-integer-overflow -fsanitize-ignorelist=ignorelist.txt foo.c ; ./a.out + # no signed-integer-overflow error + +For example, supplying the above ``ignorelist.txt`` to +``-fsanitize-ignorelist=ignorelist.txt`` disables overflow sanitizer +instrumentation for arithmetic operations containing values of type ``int``. + +The ``=sanitize`` category is also supported. Any types assigned to the +``sanitize`` category will have their sanitizer instrumentation remain. If the +same type appears within or across ignorelists with different categories the +``sanitize`` category takes precedence -- regardless of order. + +With this, one may disable instrumentation for some or all types and +specifically allow instrumentation for one or many types -- including types +created via ``typedef``. This is a way to achieve a sort of "allowlist" for +supported sanitizers. + +.. code-block:: bash + + $ cat ignorelist.txt + [implicit-signed-integer-truncation] + type:* + type:T=sanitize + + $ cat foo.c + typedef char T; + typedef char U; + void foo(int toobig) { + T a = toobig; // instrumented + U b = toobig; // not instrumented + char c = toobig; // also not instrumented + } + Format ====== diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 4c1455a3e1bb..fb0c051dc191 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -838,6 +838,9 @@ class ASTContext : public RefCountedBase { const NoSanitizeList &getNoSanitizeList() const { return *NoSanitizeL; } + bool isTypeIgnoredBySanitizer(const SanitizerMask &Mask, + const QualType &Ty) const; + const XRayFunctionFilter &getXRayFilter() const { return *XRayFilter; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d248084666d1..11e79d296cbe 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -831,6 +831,15 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( return CanonTTP; } +/// Check if a type can have its sanitizer instrumentation elided based on its +/// presence within an ignorelist. +bool ASTContext::isTypeIgnoredBySanitizer(const SanitizerMask &Mask, + const QualType &Ty) const { + std::string TyName = Ty.getUnqualifiedType().getAsString(getPrintingPolicy()); + return NoSanitizeL->containsType(Mask, TyName) && + !NoSanitizeL->containsType(Mask, TyName, "sanitize"); +} + TargetCXXABI::Kind ASTContext::getCXXABIKind() const { auto Kind = getTargetInfo().getCXXABI().getKind(); return getLangOpts().CXXABI.value_or(Kind); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 9e2c2ad5e025..287d911e10ba 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -197,6 +197,18 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) { if (!Op.mayHaveIntegerOverflow()) return true; + if (Op.Ty->isSignedIntegerType() && + Ctx.isTypeIgnoredBySanitizer(SanitizerKind::SignedIntegerOverflow, + Op.Ty)) { + return true; + } + + if (Op.Ty->isUnsignedIntegerType() && + Ctx.isTypeIgnoredBySanitizer(SanitizerKind::UnsignedIntegerOverflow, + Op.Ty)) { + return true; + } + const UnaryOperator *UO = dyn_cast(Op.E); if (UO && UO->getOpcode() == UO_Minus && @@ -1125,6 +1137,10 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType, if (!CGF.SanOpts.has(Check.second.second)) return; + // Does some SSCL ignore this type? + if (CGF.getContext().isTypeIgnoredBySanitizer(Check.second.second, DstType)) + return; + llvm::Constant *StaticArgs[] = { CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType), CGF.EmitCheckTypeDescriptor(DstType), @@ -1235,6 +1251,15 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, // Because here sign change check is interchangeable with truncation check. return; } + // Does an SSCL have an entry for the DstType under its respective sanitizer + // section? + if (DstSigned && CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::ImplicitSignedIntegerTruncation, DstType)) + return; + if (!DstSigned && + CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::ImplicitUnsignedIntegerTruncation, DstType)) + return; // That's it. We can't rule out any more cases with the data we have. CodeGenFunction::SanitizerScope SanScope(&CGF); @@ -2784,10 +2809,11 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior( return Builder.CreateNSWAdd(InVal, Amount, Name); [[fallthrough]]; case LangOptions::SOB_Trapping: - if (!E->canOverflow()) + BinOpInfo Info = createBinOpInfoFromIncDec( + E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())); + if (!E->canOverflow() || CanElideOverflowCheck(CGF.getContext(), Info)) return Builder.CreateNSWAdd(InVal, Amount, Name); - return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( - E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); + return EmitOverflowCheckedBinOp(Info); } llvm_unreachable("Unknown SignedOverflowBehaviorTy"); } @@ -2990,7 +3016,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, value = EmitIncDecConsiderOverflowBehavior(E, value, isInc); } else if (E->canOverflow() && type->isUnsignedIntegerType() && CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) && - !excludeOverflowPattern) { + !excludeOverflowPattern && + !CGF.getContext().isTypeIgnoredBySanitizer( + SanitizerKind::UnsignedIntegerOverflow, E->getType())) { value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec( E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts()))); } else { diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test new file mode 100644 index 000000000000..4b4f87326dbe --- /dev/null +++ b/clang/test/CodeGen/ubsan-type-ignorelist-category-2.test @@ -0,0 +1,58 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-0.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-1.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-2.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-3.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-4.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-5.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-6.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/order-7.ignorelist -emit-llvm %t/test.c -o - | FileCheck %s + +// The same type can appear multiple times within an ignorelist. This is a test +// to make sure "=sanitize" has priority regardless of the order in which +// duplicate type entries appear. This is a precautionary measure; we would +// much rather eagerly sanitize than silently forgo sanitization. + +//--- order-0.ignorelist +type:int +type:int=sanitize + +//--- order-1.ignorelist +type:int=sanitize +type:int + +//--- order-2.ignorelist +type:in* +type:int=sanitize + +//--- order-3.ignorelist +type:in*=sanitize +type:int + +//--- order-4.ignorelist +type:int +type:in*=sanitize + +//--- order-5.ignorelist +type:int=sanitize +type:in* + +//--- order-6.ignorelist +type:int=sanitize +type:in* + +//--- order-7.ignorelist +type:int +type:int=sanitize + + + + +//--- test.c +// CHECK-LABEL: @test +void test(int A) { +// CHECK: @llvm.sadd.with.overflow.i32 + ++A; +} diff --git a/clang/test/CodeGen/ubsan-type-ignorelist-category.test b/clang/test/CodeGen/ubsan-type-ignorelist-category.test new file mode 100644 index 000000000000..500c58f2165c --- /dev/null +++ b/clang/test/CodeGen/ubsan-type-ignorelist-category.test @@ -0,0 +1,98 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Verify ubsan doesn't emit checks for ignorelisted types +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/int.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosection.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/nosan-same-as-no-category.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=INT +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-ignorelist=%t/myty.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=MYTY +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/trunc.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsanitize=implicit-signed-integer-truncation,implicit-unsigned-integer-truncation -fsanitize-ignorelist=%t/docs.ignorelist -emit-llvm %t/test.cpp -o - | FileCheck %s --check-prefix=TRUNC2 + +//--- int.ignorelist +[{unsigned-integer-overflow,signed-integer-overflow}] +type:int + +//--- nosection.ignorelist +type:int + +//--- nosan-same-as-no-category.ignorelist +type:int + +//--- myty.ignorelist +[{unsigned-integer-overflow,signed-integer-overflow}] +type:* +type:myty=sanitize + +//--- trunc.ignorelist +[{implicit-signed-integer-truncation,implicit-unsigned-integer-truncation}] +type:char +type:unsigned char + +//--- docs.ignorelist +[implicit-signed-integer-truncation] +type:* +type:T=sanitize + +//--- test.cpp +// INT-LABEL: ignore_int +void ignore_int(int A, int B, unsigned C, unsigned D, long E) { +// INT: llvm.uadd.with.overflow.i32 + (void)(C+D); +// INT-NOT: llvm.sadd.with.overflow.i32 + (void)(A+B); +// INT: llvm.sadd.with.overflow.i64 + (void)(++E); +} + + +typedef unsigned long myty; +typedef myty derivative; +// INT-LABEL: ignore_all_except_myty +// MYTY-LABEL: ignore_all_except_myty +void ignore_all_except_myty(myty A, myty B, int C, unsigned D, derivative E) { +// MYTY-NOT: llvm.sadd.with.overflow.i32 + (void)(++C); + +// MYTY-NOT: llvm.uadd.with.overflow.i32 + (void)(D+D); + +// MYTY-NOT: llvm.umul.with.overflow.i64 + (void)(E*2); + +// MYTY: llvm.uadd.with.overflow.i64 + (void)(A+B); +} + +// INT-LABEL: truncation +// MYTY-LABEL: truncation +// TRUNC-LABEL: truncation +void truncation(char A, int B, unsigned char C, short D) { +// TRUNC-NOT: %handler.implicit_conversion + A = B; +// TRUNC-NOT: %handler.implicit_conversion + A = C; +// TRUNC-NOT: %handler.implicit_conversion + C = B; + +// TRUNC: %handler.implicit_conversion + D = B; + + (void)A; + (void)D; +} + + +// Matches the example from clang/docs/SanitizerSpecialCaseList.rst +typedef char T; +typedef char U; +// TRUNC2-LABEL: docs_example +void docs_example(int toobig) { +// TRUNC2: %handler.implicit_conversion + T a = toobig; +// TRUNC2-NOT: %handler.implicit_conversion + U b = toobig; +// TRUNC2-NOT: %handler.implicit_conversion + char c = toobig; +} + From 263775c0fd721d09e6205cd77c7c0cf72003966c Mon Sep 17 00:00:00 2001 From: David Green Date: Mon, 4 Nov 2024 08:30:11 +0000 Subject: [PATCH 5/6] [AArch64] Extend and cleanup load.ll test. NFC Adds some sext/zext variants of the scalar tests. --- llvm/test/CodeGen/AArch64/load.ll | 274 +++++++++++++++++++++--------- 1 file changed, 197 insertions(+), 77 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/load.ll b/llvm/test/CodeGen/AArch64/load.ll index 70ab10e71687..543605a0a092 100644 --- a/llvm/test/CodeGen/AArch64/load.ll +++ b/llvm/test/CodeGen/AArch64/load.ll @@ -4,110 +4,230 @@ ; ===== Legal Scalars ===== -define i8 @load_i8(ptr %ptr){ +define i8 @load_i8(ptr %ptr) { ; CHECK-LABEL: load_i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ldrb w0, [x0] ; CHECK-NEXT: ret - %a = load i8 , ptr %ptr - ret i8 %a + %a = load i8, ptr %ptr + ret i8 %a } -define i16 @load_i16(ptr %ptr){ +define i16 @load_i8_s16(ptr %ptr) { +; CHECK-LABEL: load_i8_s16: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsb w0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = sext i8 %a to i16 + ret i16 %s +} + +define i16 @load_i8_u16(ptr %ptr) { +; CHECK-LABEL: load_i8_u16: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrb w0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = zext i8 %a to i16 + ret i16 %s +} + +define i32 @load_i8_s32(ptr %ptr) { +; CHECK-LABEL: load_i8_s32: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsb w0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = sext i8 %a to i32 + ret i32 %s +} + +define i32 @load_i8_u32(ptr %ptr) { +; CHECK-LABEL: load_i8_u32: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrb w0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = zext i8 %a to i32 + ret i32 %s +} + +define i64 @load_i8_s64(ptr %ptr) { +; CHECK-LABEL: load_i8_s64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsb x0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = sext i8 %a to i64 + ret i64 %s +} + +define i64 @load_i8_u64(ptr %ptr) { +; CHECK-LABEL: load_i8_u64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrb w0, [x0] +; CHECK-NEXT: ret + %a = load i8, ptr %ptr + %s = zext i8 %a to i64 + ret i64 %s +} + +define i16 @load_i16(ptr %ptr) { ; CHECK-LABEL: load_i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ldrh w0, [x0] ; CHECK-NEXT: ret - %a = load i16 , ptr %ptr - ret i16 %a + %a = load i16, ptr %ptr + ret i16 %a } -define i32 @load_i32(ptr %ptr){ +define i32 @load_i16_s32(ptr %ptr) { +; CHECK-LABEL: load_i16_s32: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsh w0, [x0] +; CHECK-NEXT: ret + %a = load i16, ptr %ptr + %s = sext i16 %a to i32 + ret i32 %s +} + +define i32 @load_i16_u32(ptr %ptr) { +; CHECK-LABEL: load_i16_u32: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrh w0, [x0] +; CHECK-NEXT: ret + %a = load i16, ptr %ptr + %s = zext i16 %a to i32 + ret i32 %s +} + +define i64 @load_i16_s64(ptr %ptr) { +; CHECK-LABEL: load_i16_s64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsh x0, [x0] +; CHECK-NEXT: ret + %a = load i16, ptr %ptr + %s = sext i16 %a to i64 + ret i64 %s +} + +define i64 @load_i16_u64(ptr %ptr) { +; CHECK-LABEL: load_i16_u64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrh w0, [x0] +; CHECK-NEXT: ret + %a = load i16, ptr %ptr + %s = zext i16 %a to i64 + ret i64 %s +} + +define i32 @load_i32(ptr %ptr) { ; CHECK-LABEL: load_i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: ret - %a = load i32 , ptr %ptr - ret i32 %a + %a = load i32, ptr %ptr + ret i32 %a +} + +define i64 @load_i32_s64(ptr %ptr) { +; CHECK-LABEL: load_i32_s64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldrsw x0, [x0] +; CHECK-NEXT: ret + %a = load i32, ptr %ptr + %s = sext i32 %a to i64 + ret i64 %s +} + +define i64 @load_i32_u64(ptr %ptr) { +; CHECK-LABEL: load_i32_u64: +; CHECK: // %bb.0: +; CHECK-NEXT: ldr w0, [x0] +; CHECK-NEXT: ret + %a = load i32, ptr %ptr + %s = zext i32 %a to i64 + ret i64 %s } -define i64 @load_i64(ptr %ptr){ +define i64 @load_i64(ptr %ptr) { ; CHECK-LABEL: load_i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr x0, [x0] ; CHECK-NEXT: ret - %a = load i64 , ptr %ptr - ret i64 %a + %a = load i64, ptr %ptr + ret i64 %a } ; ===== Legal Vector Types ===== -define <8 x i8> @load_v8i8(ptr %ptr){ +define <8 x i8> @load_v8i8(ptr %ptr) { ; CHECK-LABEL: load_v8i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr d0, [x0] ; CHECK-NEXT: ret - %a = load <8 x i8>, ptr %ptr - ret <8 x i8> %a + %a = load <8 x i8>, ptr %ptr + ret <8 x i8> %a } -define <16 x i8> @load_v16i8(ptr %ptr){ +define <16 x i8> @load_v16i8(ptr %ptr) { ; CHECK-LABEL: load_v16i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: ret - %a = load <16 x i8>, ptr %ptr - ret <16 x i8> %a + %a = load <16 x i8>, ptr %ptr + ret <16 x i8> %a } -define <4 x i16> @load_v4i16(ptr %ptr){ +define <4 x i16> @load_v4i16(ptr %ptr) { ; CHECK-LABEL: load_v4i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr d0, [x0] ; CHECK-NEXT: ret - %a = load <4 x i16>, ptr %ptr - ret <4 x i16> %a + %a = load <4 x i16>, ptr %ptr + ret <4 x i16> %a } -define <8 x i16> @load_v8i16(ptr %ptr){ +define <8 x i16> @load_v8i16(ptr %ptr) { ; CHECK-LABEL: load_v8i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: ret - %a = load <8 x i16>, ptr %ptr - ret <8 x i16> %a + %a = load <8 x i16>, ptr %ptr + ret <8 x i16> %a } -define <2 x i32> @load_v2i32(ptr %ptr){ +define <2 x i32> @load_v2i32(ptr %ptr) { ; CHECK-LABEL: load_v2i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr d0, [x0] ; CHECK-NEXT: ret - %a = load <2 x i32>, ptr %ptr - ret <2 x i32> %a + %a = load <2 x i32>, ptr %ptr + ret <2 x i32> %a } -define <4 x i32> @load_v4i32(ptr %ptr){ +define <4 x i32> @load_v4i32(ptr %ptr) { ; CHECK-LABEL: load_v4i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: ret - %a = load <4 x i32>, ptr %ptr - ret <4 x i32> %a + %a = load <4 x i32>, ptr %ptr + ret <4 x i32> %a } -define <2 x i64> @load_v2i64(ptr %ptr){ +define <2 x i64> @load_v2i64(ptr %ptr) { ; CHECK-LABEL: load_v2i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: ret - %a = load <2 x i64>, ptr %ptr - ret <2 x i64> %a + %a = load <2 x i64>, ptr %ptr + ret <2 x i64> %a } ; ===== Smaller/Larger Width Vectors with Legal Element Sizes ===== -define <2 x i8> @load_v2i8(ptr %ptr, <2 x i8> %b){ +define <2 x i8> @load_v2i8(ptr %ptr, <2 x i8> %b) { ; CHECK-SD-LABEL: load_v2i8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ld1 { v0.b }[0], [x0] @@ -123,30 +243,30 @@ define <2 x i8> @load_v2i8(ptr %ptr, <2 x i8> %b){ ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret - %a = load <2 x i8>, ptr %ptr - ret <2 x i8> %a + %a = load <2 x i8>, ptr %ptr + ret <2 x i8> %a } -define i32 @load_v4i8(ptr %ptr, <4 x i8> %b){ +define i32 @load_v4i8(ptr %ptr, <4 x i8> %b) { ; CHECK-LABEL: load_v4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: ret - %a = load <4 x i8>, ptr %ptr - %c = bitcast <4 x i8> %a to i32 - ret i32 %c + %a = load <4 x i8>, ptr %ptr + %c = bitcast <4 x i8> %a to i32 + ret i32 %c } -define <32 x i8> @load_v32i8(ptr %ptr){ +define <32 x i8> @load_v32i8(ptr %ptr) { ; CHECK-LABEL: load_v32i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: ret - %a = load <32 x i8>, ptr %ptr - ret <32 x i8> %a + %a = load <32 x i8>, ptr %ptr + ret <32 x i8> %a } -define <2 x i16> @load_v2i16(ptr %ptr){ +define <2 x i16> @load_v2i16(ptr %ptr) { ; CHECK-SD-LABEL: load_v2i16: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ld1 { v0.h }[0], [x0] @@ -162,49 +282,49 @@ define <2 x i16> @load_v2i16(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret - %a = load <2 x i16>, ptr %ptr - ret <2 x i16> %a + %a = load <2 x i16>, ptr %ptr + ret <2 x i16> %a } -define <16 x i16> @load_v16i16(ptr %ptr){ +define <16 x i16> @load_v16i16(ptr %ptr) { ; CHECK-LABEL: load_v16i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: ret - %a = load <16 x i16>, ptr %ptr - ret <16 x i16> %a + %a = load <16 x i16>, ptr %ptr + ret <16 x i16> %a } -define <1 x i32> @load_v1i32(ptr %ptr){ +define <1 x i32> @load_v1i32(ptr %ptr) { ; CHECK-LABEL: load_v1i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ldr s0, [x0] ; CHECK-NEXT: ret - %a = load <1 x i32>, ptr %ptr - ret <1 x i32> %a + %a = load <1 x i32>, ptr %ptr + ret <1 x i32> %a } -define <8 x i32> @load_v8i32(ptr %ptr){ +define <8 x i32> @load_v8i32(ptr %ptr) { ; CHECK-LABEL: load_v8i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: ret - %a = load <8 x i32>, ptr %ptr - ret <8 x i32> %a + %a = load <8 x i32>, ptr %ptr + ret <8 x i32> %a } -define <4 x i64> @load_v4i64(ptr %ptr){ +define <4 x i64> @load_v4i64(ptr %ptr) { ; CHECK-LABEL: load_v4i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: ret - %a = load <4 x i64>, ptr %ptr - ret <4 x i64> %a + %a = load <4 x i64>, ptr %ptr + ret <4 x i64> %a } ; ===== Vectors with Non-Pow 2 Widths ===== -define <3 x i8> @load_v3i8(ptr %ptr){ +define <3 x i8> @load_v3i8(ptr %ptr) { ; CHECK-SD-LABEL: load_v3i8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr s0, [x0] @@ -220,11 +340,11 @@ define <3 x i8> @load_v3i8(ptr %ptr){ ; CHECK-GI-NEXT: ldrb w2, [x0, #2] ; CHECK-GI-NEXT: mov w0, w8 ; CHECK-GI-NEXT: ret - %a = load <3 x i8>, ptr %ptr - ret <3 x i8> %a + %a = load <3 x i8>, ptr %ptr + ret <3 x i8> %a } -define <7 x i8> @load_v7i8(ptr %ptr){ +define <7 x i8> @load_v7i8(ptr %ptr) { ; CHECK-SD-LABEL: load_v7i8: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr d0, [x0] @@ -248,11 +368,11 @@ define <7 x i8> @load_v7i8(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.b[6], v1.b[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret - %a = load <7 x i8>, ptr %ptr - ret <7 x i8> %a + %a = load <7 x i8>, ptr %ptr + ret <7 x i8> %a } -define <3 x i16> @load_v3i16(ptr %ptr){ +define <3 x i16> @load_v3i16(ptr %ptr) { ; CHECK-SD-LABEL: load_v3i16: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr d0, [x0] @@ -267,11 +387,11 @@ define <3 x i16> @load_v3i16(ptr %ptr){ ; CHECK-GI-NEXT: ld1 { v0.h }[2], [x8] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret - %a = load <3 x i16>, ptr %ptr - ret <3 x i16> %a + %a = load <3 x i16>, ptr %ptr + ret <3 x i16> %a } -define <7 x i16> @load_v7i16(ptr %ptr){ +define <7 x i16> @load_v7i16(ptr %ptr) { ; CHECK-SD-LABEL: load_v7i16: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr q0, [x0] @@ -293,11 +413,11 @@ define <7 x i16> @load_v7i16(ptr %ptr){ ; CHECK-GI-NEXT: add x8, x0, #12 ; CHECK-GI-NEXT: ld1 { v0.h }[6], [x8] ; CHECK-GI-NEXT: ret - %a = load <7 x i16>, ptr %ptr - ret <7 x i16> %a + %a = load <7 x i16>, ptr %ptr + ret <7 x i16> %a } -define <3 x i32> @load_v3i32(ptr %ptr){ +define <3 x i32> @load_v3i32(ptr %ptr) { ; CHECK-SD-LABEL: load_v3i32: ; CHECK-SD: // %bb.0: ; CHECK-SD-NEXT: ldr q0, [x0] @@ -311,8 +431,8 @@ define <3 x i32> @load_v3i32(ptr %ptr){ ; CHECK-GI-NEXT: add x8, x0, #8 ; CHECK-GI-NEXT: ld1 { v0.s }[2], [x8] ; CHECK-GI-NEXT: ret - %a = load <3 x i32>, ptr %ptr - ret <3 x i32> %a + %a = load <3 x i32>, ptr %ptr + ret <3 x i32> %a } define <2 x i128> @load_v2i128(ptr %p) { @@ -333,8 +453,8 @@ define <2 x i128> @load_v2i128(ptr %p) { ; CHECK-GI-NEXT: fmov x1, d2 ; CHECK-GI-NEXT: fmov x3, d3 ; CHECK-GI-NEXT: ret - %a = load <2 x i128>, ptr %p - ret <2 x i128> %a + %a = load <2 x i128>, ptr %p + ret <2 x i128> %a } define <2 x fp128> @load_v2f128(ptr %p) { @@ -342,6 +462,6 @@ define <2 x fp128> @load_v2f128(ptr %p) { ; CHECK: // %bb.0: ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: ret - %a = load <2 x fp128>, ptr %p - ret <2 x fp128> %a + %a = load <2 x fp128>, ptr %p + ret <2 x fp128> %a } From cec147ae5cb9debd74cc3dc2bca12e8cd8a30831 Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Mon, 4 Nov 2024 09:33:55 +0100 Subject: [PATCH 6/6] [ASan][test] Enable ASan tests on SPARC (#107405) With PR #107223 and PR #107403, ASan testing can be enabled on SPARC. This patch does so, 32-bit only on both Solaris and Linux. There is no 64-bit support even in GCC. Apart from the obvious CMake changes, this patch includes a couple of testcase adjustments necessary for SPARC: - In `asan_oob_test.cpp`, the `OOB_int` subtest needs to be disabled: it performs unaligned accesses that cannot work on a strict-alignment target like SPARC. - `asan_test.cpp` needs to disable subtests that depend on support for `__builtin_setjmp` and `__builtin_longjmp`. - `zero_page_pc.cpp` reports `0x5` as the faulting address on access to `0x4`. I don't really know why, but it's consistent between Solaris and Linux. Tested on `sparcv9-sun-solaris2.11` and `sparc64-unknown-linux-gnu`. --- compiler-rt/lib/asan/tests/CMakeLists.txt | 2 +- compiler-rt/lib/asan/tests/asan_oob_test.cpp | 9 ++++++++- compiler-rt/lib/asan/tests/asan_test.cpp | 2 +- compiler-rt/test/asan/CMakeLists.txt | 2 +- compiler-rt/test/asan/TestCases/zero_page_pc.cpp | 2 +- compiler-rt/test/sanitizer_common/CMakeLists.txt | 2 +- compiler-rt/test/ubsan/CMakeLists.txt | 4 ++-- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index 0c4b0361ec49..998e0ff24efa 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -244,7 +244,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND NOT ANDROID) if(APPLE) darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) endif() - list(REMOVE_ITEM ASAN_TEST_ARCH sparc sparcv9) + list(REMOVE_ITEM ASAN_TEST_ARCH sparcv9) if(OS_NAME MATCHES "SunOS") list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) endif() diff --git a/compiler-rt/lib/asan/tests/asan_oob_test.cpp b/compiler-rt/lib/asan/tests/asan_oob_test.cpp index 56f573c1fc48..ce4c90c23e84 100644 --- a/compiler-rt/lib/asan/tests/asan_oob_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_oob_test.cpp @@ -11,6 +11,13 @@ //===----------------------------------------------------------------------===// #include "asan_test_utils.h" +#ifdef __sparc__ +// Tests using unaligned accesses cannot work on strict-alignment targets. +#define SKIP_ON_STRICT_ALIGNMENT(x) DISABLED_##x +#else +#define SKIP_ON_STRICT_ALIGNMENT(x) x +#endif + NOINLINE void asan_write_sized_aligned(uint8_t *p, size_t size) { EXPECT_EQ(0U, ((uintptr_t)p % size)); if (size == 1) asan_write((uint8_t*)p); @@ -79,7 +86,7 @@ TEST(AddressSanitizer, OOB_char) { OOBTest(); } -TEST(AddressSanitizer, OOB_int) { +TEST(AddressSanitizer, SKIP_ON_STRICT_ALIGNMENT(OOB_int)) { OOBTest(); } diff --git a/compiler-rt/lib/asan/tests/asan_test.cpp b/compiler-rt/lib/asan/tests/asan_test.cpp index 827c2ae3a9cd..09d71569f89b 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_test.cpp @@ -631,7 +631,7 @@ NOINLINE void SigLongJmpFunc1(sigjmp_buf buf) { #if !defined(__ANDROID__) && !defined(__arm__) && !defined(__aarch64__) && \ !defined(__mips__) && !defined(__mips64) && !defined(__s390__) && \ - !defined(__riscv) && !defined(__loongarch__) + !defined(__riscv) && !defined(__loongarch__) && !defined(__sparc__) NOINLINE void BuiltinLongJmpFunc1(jmp_buf buf) { // create three red zones for these two stack objects. int a; diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt index fb9e81bbe808..414a6cc9496e 100644 --- a/compiler-rt/test/asan/CMakeLists.txt +++ b/compiler-rt/test/asan/CMakeLists.txt @@ -36,7 +36,7 @@ set(ASAN_TEST_ARCH ${ASAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) endif() -list(REMOVE_ITEM ASAN_TEST_ARCH sparc sparcv9) +list(REMOVE_ITEM ASAN_TEST_ARCH sparcv9) if(OS_NAME MATCHES "SunOS") list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) endif() diff --git a/compiler-rt/test/asan/TestCases/zero_page_pc.cpp b/compiler-rt/test/asan/TestCases/zero_page_pc.cpp index 9a395ecdf37c..a7d00ce9b698 100644 --- a/compiler-rt/test/asan/TestCases/zero_page_pc.cpp +++ b/compiler-rt/test/asan/TestCases/zero_page_pc.cpp @@ -19,6 +19,6 @@ int main() { // the compiler is free to choose the order. As a result, the address is // either 0x4, 0xc or 0x14. The pc is still in main() because it has not // actually made the call when the faulting access occurs. - // CHECK: {{AddressSanitizer: (SEGV|access-violation).*(address|pc) 0x0*[4c]}} + // CHECK: {{AddressSanitizer: (SEGV|access-violation).*(address|pc) 0x0*[45c]}} return 0; } diff --git a/compiler-rt/test/sanitizer_common/CMakeLists.txt b/compiler-rt/test/sanitizer_common/CMakeLists.txt index fa06b82acebd..615666676f57 100644 --- a/compiler-rt/test/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/test/sanitizer_common/CMakeLists.txt @@ -59,7 +59,7 @@ foreach(tool ${SUPPORTED_TOOLS}) darwin_filter_host_archs(${tool_toupper}_SUPPORTED_ARCH TEST_ARCH) endif() if(${tool} STREQUAL "asan") - list(REMOVE_ITEM TEST_ARCH sparc sparcv9) + list(REMOVE_ITEM TEST_ARCH sparcv9) endif() if(OS_NAME MATCHES "SunOS" AND ${tool} STREQUAL "asan") list(REMOVE_ITEM TEST_ARCH x86_64) diff --git a/compiler-rt/test/ubsan/CMakeLists.txt b/compiler-rt/test/ubsan/CMakeLists.txt index d95f9ad649eb..9b7fbe3c8f92 100644 --- a/compiler-rt/test/ubsan/CMakeLists.txt +++ b/compiler-rt/test/ubsan/CMakeLists.txt @@ -51,10 +51,10 @@ foreach(arch ${UBSAN_TEST_ARCH}) if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};") # TODO(wwchrome): Re-enable ubsan for asan win 64-bit when ready. # Disable ubsan with AddressSanitizer tests for Windows 64-bit, - # 64-bit Solaris/x86, and SPARC. + # 64-bit Solaris/x86 and 64-bit SPARC. if((NOT (OS_NAME MATCHES "Windows" AND CMAKE_SIZEOF_VOID_P EQUAL 8)) AND (NOT (OS_NAME MATCHES "SunOS" AND ${arch} MATCHES x86_64)) AND - (NOT ${arch} MATCHES sparc)) + (NOT ${arch} MATCHES sparcv9)) add_ubsan_testsuites("AddressSanitizer" asan ${arch}) endif() endif()