claudiu.zissulescu-iancule...@oracle.com writes:
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c
> new file mode 100644
> index 00000000000..70b790c6c3e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2" } */
> +/* FIXME - scan-assembler-times-not subg ?  */
> +/* FIXME - generate stgp instead of stg + str ?  */

Were you planning to address these in this series, or are they TODOs
for future work?  Similarly for the other FIXMEs.

> +
> +int use (int *x);
> +
> +void foo (int n)
> +{
> +  int x = 99;
> +  use (&x);
> +}
> +
> +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
> +/* { dg-final { scan-assembler-times {\tstg\t} 2 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c
> new file mode 100644
> index 00000000000..2838c934a62
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/basic-3.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2" } */
> +
> +int use (int *x);
> +
> +void foo (int n)
> +{
> + int a, b, c;
> + use (&a);
> + use (&b);
> + use (&c);
> +}
> +
> +/* 3 stack vars need 48 bytes. Expected: 3 stg to tag, 1 st2g + 1 stg to
> +   untag.  */
> +
> +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
> +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 48\]\n} 1 } } */
> +/* { dg-final { scan-assembler-times {st2g\t...?, \[sp, 32\]\n} 1 } } */
> +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 32\]\n} 1 } } */
> +/* { dg-final { scan-assembler-times {stg\t...?, \[sp, 64\]\n} 2 } } */

I'm not sure this makes it sufficiently clear what bytes [16, 31] are
being used for.

> [...]
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c
> new file mode 100644
> index 00000000000..f233ce04d35
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/large-array.c
> @@ -0,0 +1,24 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2" } */
> +/* FIXME - add other checks later. For now make sure this does not ICE.  */

It looks from the dg-finals below that the test already does more than that.

> +
> +#define ARRAY_LEN 12000
> +
> +int create (void);
> +
> +void sort (int *data, int n);
> +
> +void sort_array (void)
> +{
> +  int data[ARRAY_LEN], i;
> +
> +  for (i=0; i < ARRAY_LEN; ++i)
> +    {
> +      data[i] = create ();
> +    }
> +  
> +  sort (data, ARRAY_LEN);
> +}
> +
> +/* { dg-final { scan-assembler-times {\tirg\t} 1 } } */
> +/* { dg-final { scan-assembler-times {st2g\t...?, \[...?\], 32\n} 2 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c
> new file mode 100644
> index 00000000000..173fe1135bf
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/local-no-escape.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O0" } */
> +
> +/* FIXME - If x doesnt escape the function, why should MTE tagging be done 
> for
> +   x ?  */

Do we?  I would have expected x to be optimised away by gimple.  Does that
not happen?

It's not really clear to me what this is testing.  Is it an anti-ICE test?
(No need to change it, just curious.)

> +
> +extern int use (int *x);
> +extern int bar (int *x);
> +extern int baz (int *x);
> +
> +int a[10];
> +
> +int foo (int n)
> +{
> +  int x = use (a);
> +  if (x)
> +    return bar (a);
> +  else
> +    return baz (a);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp 
> b/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp
> new file mode 100644
> index 00000000000..ba32f43d846
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/memtag.exp
> @@ -0,0 +1,64 @@
> +# Copyright (C) 2024 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with GCC; see the file COPYING3.  If not see
> +# <http://www.gnu.org/licenses/>.
> +
> +# GCC testsuite that uses the `dg.exp' driver.
> +
> +# Load support procs.
> +load_lib gcc-dg.exp
> +
> +# Return 1 if target can compile and run binary for stack
> +# sanitization, 0 otherwise.
> +
> +proc check_effective_target_memtag_exec {} {
> +    if ![check_runtime memtag_exec {
> +     #ifdef __cplusplus
> +     extern "C" {
> +     #endif
> +     extern int prctl(int, unsigned long, unsigned long, unsigned long, 
> unsigned long);
> +     #ifdef __cplusplus
> +     }
> +     #endif
> +     int main (void) {
> +     #define PR_SET_TAGGED_ADDR_CTRL 55
> +     #define PR_GET_TAGGED_ADDR_CTRL 56
> +     #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
> +     #define PR_MTE_TCF_SYNC (1UL << 1)
> +     #define PR_MTE_TAG_SHIFT 3
> +       if (prctl (PR_GET_TAGGED_ADDR_CTRL, 0,0,0,0) == -1)
> +         return -1;
> +       if (prctl (PR_SET_TAGGED_ADDR_CTRL,
> +                  PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC
> +                  | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0) == -1
> +           || !prctl (PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0))
> +         return 1;
> +       return 0;
> +     }
> +      }] {
> +     return 0;
> +      }
> +    return 1;
> +}

I might have said this before, but this seems like it should go in
target-supports.exp.

> +# Initialize `dg'.
> +dg-init
> +
> +# Main loop.
> +if [check_effective_target_aarch64_mte] {
> +  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
> +     "" "-fsanitize=memtag-stack -march=armv8.5-a+memtag"
> +}
> +
> +# All done.
> +dg-finish
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h 
> b/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h
> new file mode 100644
> index 00000000000..efb3c6d187c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/mte-sig.h
> @@ -0,0 +1,15 @@
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <string.h>
> +
> +void handler (int nSig)
> +{
> +  /* We hit the exception.  Return error.  */
> +  exit (1);
> +}
> +
> +
> +static void setHandler (void)
> +{
> +  signal (SIGSEGV, handler);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c
> new file mode 100644
> index 00000000000..0d40063dc08
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/no-sanitize-attribute.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2" } */
> +
> +int use (int *x);
> +
> +__attribute__((no_sanitize("memtag-stack")))
> +void foo (int n)
> +{
> +  int x = 99;
> +  use (&x);
> +}
> +
> +/* { dg-final { scan-assembler-not "irg" } } */
> +/* { dg-final { scan-assembler-not "stg" } } */
> +/* { dg-final { scan-assembler-not "st2g" } } */
> +/* { dg-final { scan-assembler-not "subg" } } */
> +/* { dg-final { scan-assembler-not "addg" } } */

It's probably worth adding \t to the beginning of each string,
so that we don't accidentally match fragments of filenames.

> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c
> new file mode 100644
> index 00000000000..b63619b04d3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/texec-1.c
> @@ -0,0 +1,27 @@
> +/* { dg-do run { xfail *-*-* } } */

Why are all but one of the run tests XFAILed?

> +/* { dg-require-effective-target memtag_exec } */
> +/* { dg-additional-options "-O2" } */
> +
> +#include "mte-sig.h"
> +
> +void  __attribute__((noinline))
> +use (volatile unsigned char *ptr)
> +{
> +  ptr[0] = 0x41;
> +  ptr[1] = 0x42;
> +}
> +
> +int main(void)
> +{
> +  volatile unsigned char array[15];
> +  volatile unsigned char *ptr = &array[0];
> +
> +  setHandler();
> +  use (ptr);
> +
> +  /* Write to memory beyond the 16 byte granule (offsest 0x10) MTE should
> +     generate an exception If the offset is less than 0x10 no SIGSEGV will
> +     occur.  */
> +  ptr[0x10] = 0x55;
> +  return 0;
> +}
> [...]
> diff --git a/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c 
> b/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c
> new file mode 100644
> index 00000000000..c960048d670
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/memtag/vararray-gimple.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-fdump-tree-asan -O2" } */
> +/* { dg-skip-if "" { *-*-* }  { "-O0" } { "" } } */

The last line shouldn't be necessary, since AFAICT each test is only run once,
with -O2 in this case.

Otherwise it looks good, thanks.

Richard

> +
> +extern int *use (int *b, int n);
> +
> +int *foo (int n)
> +{
> +  int b[n];
> +  return use (b, n);
> +}
> +
> +/* HWASAN_ALLOCA_POISON is used for alloca and VLAs when MEMTAG is in effect.
> +   Although HWASAN_ALLOCA_UNPOISON is (also) used for untagging frame, it
> +   doesnt hurt to check it in context of the current test.  */
> +/* { dg-final { scan-tree-dump "HWASAN_ALLOCA_POISON" "asan1" } } */
> +/* { dg-final { scan-tree-dump "HWASAN_ALLOCA_UNPOISON" "asan1" } } */

Reply via email to