public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] aarch64: Hybrid support for non-TLS CADI symbols
@ 2022-05-05 12:09 Matthew Malcomson
  0 siblings, 0 replies; only message in thread
From: Matthew Malcomson @ 2022-05-05 12:09 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c29d908fa60c52faf58f946fcbb2b1f98a83da6b

commit c29d908fa60c52faf58f946fcbb2b1f98a83da6b
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Wed Apr 13 10:05:22 2022 +0100

    aarch64: Hybrid support for non-TLS CADI symbols
    
    I think this patch contains the minimum changes needed to code-generate
    an existing non-TLS CAP_ADDR_EXPR for hybrid code.  Any non-TLS CADI
    symbolic constant needs to be forced into a .data.rel.ro(.local)
    .capinit slot and then be loaded from there.

Diff:
---
 gcc/config/aarch64/aarch64.c                       | 19 +++++++----
 gcc/explow.c                                       |  9 +++--
 gcc/expr.c                                         | 38 +++++++++++++++++-----
 .../aarch64/morello/hybrid-addr-expr-1.c           | 20 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-2.c           | 21 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-3.c           | 21 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-4.c           | 21 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-5.c           | 21 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-6.c           | 21 ++++++++++++
 .../aarch64/morello/hybrid-addr-expr-7.c           | 23 +++++++++++++
 .../aarch64/morello/hybrid-addr-expr-8.c           | 22 +++++++++++++
 11 files changed, 219 insertions(+), 17 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index b503e5dfd65..b5bc8949b2c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -5537,11 +5537,12 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	}
 
       sty = aarch64_classify_symbol (base, const_offset);
+      scalar_addr_mode mem_mode = TARGET_ILP32 ? ptr_mode : addr_mode;
       switch (sty)
 	{
 	case SYMBOL_FORCE_TO_MEM:
 	  if (const_offset != 0
-	      && targetm.cannot_force_const_mem (addr_mode, imm))
+	      && targetm.cannot_force_const_mem (mem_mode, imm))
 	    {
 	      gcc_assert (can_create_pseudo_p ());
 	      base = aarch64_force_temporary (addr_mode, dest, base);
@@ -5550,7 +5551,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	      return;
 	    }
 
-	  mem = force_const_mem (ptr_mode, imm);
+	  mem = force_const_mem (mem_mode, imm);
 	  if (TARGET_CAPABILITY_PURE && SYMBOL_REF_P (base))
 	    {
 	      /* Mark the symbol created by `force_const_mem` as one into the
@@ -5570,7 +5571,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	     we need to expand the literal pool access carefully.
 	     This is something that needs to be done in a number
 	     of places, so could well live as a separate function.  */
-	  if (!memory_operand (mem, ptr_mode))
+	  if (!memory_operand (mem, mem_mode))
 	    {
 	      gcc_assert (can_create_pseudo_p ());
 	      if (TARGET_CAPABILITY_PURE && SYMBOL_REF_P (base))
@@ -5605,10 +5606,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 		  if (ptr_mode != Pmode)
 		    base = convert_memory_address (Pmode, base);
 		}
-	      mem = gen_rtx_MEM (ptr_mode, base);
+	      mem = gen_rtx_MEM (mem_mode, base);
 	    }
 
-	  if (addr_mode != ptr_mode)
+	  if (addr_mode != mem_mode)
 	    mem = gen_rtx_ZERO_EXTEND (addr_mode, mem);
 
 	  emit_insn (gen_rtx_SET (dest, mem));
@@ -9366,7 +9367,7 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
       else
 	/* Avoid generating a 64-bit relocation in ILP32; leave
 	   to aarch64_expand_mov_immediate to handle it properly.  */
-	return mode != ptr_mode;
+	return TARGET_ILP32 && mode != ptr_mode;
     }
 
   return aarch64_tls_referenced_p (x);
@@ -17110,6 +17111,12 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
       if (aarch64_sym_indirectly_accessed_p (x))
 	return aarch64_classify_capability_symbol (x, offset);
 
+      /* In hybrid mode, the only way of loading a constant capability is
+	 to force it into a (.data.rel.ro*) constant pool entry.  Unlike
+	 for pure capabilities, the GOT option is not available.  */
+      if (CAPABILITY_MODE_P (GET_MODE (x)) && !CAPABILITY_MODE_P (Pmode))
+	return SYMBOL_FORCE_TO_MEM;
+
       /* -mpc-relative-literal-loads tells us to assume that all (function)
 	 constant pool entries will be within the range of PC-relative LDR,
 	 which means that they must also be in range of ADR.  */
diff --git a/gcc/explow.c b/gcc/explow.c
index 00e89e32689..e58e5923f2a 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -363,11 +363,16 @@ convert_memory_address_addr_space_1 (scalar_addr_mode to_mode ATTRIBUTE_UNUSED,
   /* If X already has the right mode, just return it.  */
   if (GET_MODE (x) == to_mode)
     return x;
-  /* We can't convert a mode to a capability mode.
+  /* Non-capability symbolic constants can be re-expressed as capability
+     constants simply by (recursively) changing the mode.  However,
+     we can't convert an arbitrary runtime value to a capability mode.
      Even if the from_mode was a capability mode there is no general way to
      handle that since we don't know what the extra bits contain in each case
      (they're not just simply bits ...).  */
-  gcc_assert (! CAPABILITY_MODE_P (to_mode));
+  gcc_assert (! CAPABILITY_MODE_P (to_mode)
+	      || GET_CODE (x) == LABEL_REF
+	      || GET_CODE (x) == SYMBOL_REF
+	      || GET_CODE (x) == CONST);
 
   pointer_mode = unqualified_pointer_mode (as);
   address_mode = unqualified_address_mode (as);
diff --git a/gcc/expr.c b/gcc/expr.c
index d48dfc6bccf..5fe7e9781f7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8178,12 +8178,14 @@ expand_expr_constant (tree exp, int defer, enum expand_modifier modifier)
   return mem;
 }
 
-/* A subroutine of expand_expr_addr_expr.  Evaluate the address of EXP.
-   The TARGET, TMODE and MODIFIER arguments are as for expand_expr.  */
+/* A subroutine of expand_expr_addr_expr.  Evaluate the address of EXP
+   using code ADDR_CODE.  The TARGET, TMODE and MODIFIER arguments are
+   as for expand_expr.  */
 
 static rtx
-expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
-		         enum expand_modifier modifier, addr_space_t as)
+expand_expr_addr_expr_1 (tree_code addr_code, tree exp, rtx target,
+			 scalar_addr_mode tmode,
+			 enum expand_modifier modifier, addr_space_t as)
 {
   rtx result, subtarget;
   tree inner, offset;
@@ -8191,6 +8193,11 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
   int unsignedp, reversep, volatilep = 0;
   machine_mode mode1;
 
+  /* Detect if we're creating a capability pointer in an environment
+     where that isn't the default behavior.  */
+  bool force_capability = (addr_code == CAP_ADDR_EXPR
+			   && !CAPABILITY_MODE_P (Pmode));
+
   /* If we are taking the address of a constant and are at the top level,
      we have to use output_constant_def since we can't call force_const_mem
      at top level.  */
@@ -8256,7 +8263,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
 	 the initializers aren't gimplified.  */
       if (COMPOUND_LITERAL_EXPR_DECL (exp)
 	  && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
-	return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp),
+	return expand_expr_addr_expr_1 (addr_code,
+					COMPOUND_LITERAL_EXPR_DECL (exp),
 					target, tmode, modifier, as);
       /* FALLTHRU */
     default:
@@ -8271,8 +8279,13 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
 	  || TREE_CODE (exp) == CONSTRUCTOR
 	  || TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
 	{
+	  /* If we want a capability pointer, and if normal pointers are
+	     not capabilities, try harder to preserve the structure of
+	     the original address.  In particular, don't try to rewrite
+	     the address to use (Pmode) section anchors.  */
 	  result = expand_expr (exp, target, tmode,
 				modifier == EXPAND_INITIALIZER
+				|| force_capability
 				? EXPAND_INITIALIZER : EXPAND_CONST_ADDRESS);
 
 	  /* If the DECL isn't in memory, then the DECL wasn't properly
@@ -8282,6 +8295,11 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
 	  gcc_assert (MEM_P (result));
 	  result = XEXP (result, 0);
 
+	  /* Convert a non-capability constant address to a capability
+	     while we still have its original form.  */
+	  if (force_capability)
+	    result = convert_memory_address_addr_space (tmode, result, as);
+
 	  /* ??? Is this needed anymore?  */
 	  if (DECL_P (exp))
 	    TREE_USED (exp) = 1;
@@ -8317,7 +8335,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_addr_mode tmode,
       SET_TYPE_ALIGN (TREE_TYPE (inner), TYPE_ALIGN (TREE_TYPE (exp)));
       TYPE_USER_ALIGN (TREE_TYPE (inner)) = 1;
     }
-  result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier, as);
+  result = expand_expr_addr_expr_1 (addr_code, inner, subtarget, tmode,
+				    modifier, as);
 
   if (offset)
     {
@@ -8393,8 +8412,8 @@ expand_expr_addr_expr (tree exp, rtx target, machine_mode tmode,
 				? pointer_mode
 				: address_mode);
 
-  result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
-				    new_tmode, modifier, as);
+  result = expand_expr_addr_expr_1 (TREE_CODE (exp), TREE_OPERAND (exp, 0),
+				    target, new_tmode, modifier, as);
 
   /* Despite expand_expr claims concerning ignoring TMODE when not
      strictly convenient, stuff breaks if we don't honor it.  Note
@@ -10600,7 +10619,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	     gracefully.  */
 	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
 	  scalar_addr_mode address_mode = unqualified_address_mode (as);
-	  op0 = expand_expr_addr_expr_1 (exp, NULL_RTX, address_mode,
+	  op0 = expand_expr_addr_expr_1 (unqualified_addr_expr (), exp,
+					 NULL_RTX, address_mode,
 					 EXPAND_NORMAL, as);
 	  op0 = memory_address_addr_space (mode, op0, as);
 	  temp = gen_rtx_MEM (mode, op0);
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-1.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-1.c
new file mode 100644
index 00000000000..175471ef26f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-1.c
@@ -0,0 +1,20 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=tiny -fno-PIC -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	ldr	c0, \.LC0
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro\.local,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-2.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-2.c
new file mode 100644
index 00000000000..b1a724f2158
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-2.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=tiny -fPIC -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	ldr	c0, \.LC0
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\tldr\tc0, \.LC0\n\tret\n} } } */
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-3.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-3.c
new file mode 100644
index 00000000000..512c517c8c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-3.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=small -fno-PIC -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	adrp	(x[0-9]+), \.LC0
+**	ldr	c0, \[\1, #:lo12:\.LC0\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro\.local,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-4.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-4.c
new file mode 100644
index 00000000000..9f6ab6a54ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-4.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=small -fPIC -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	adrp	(x[0-9]+), \.LC0
+**	ldr	c0, \[\1, #:lo12:\.LC0\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-5.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-5.c
new file mode 100644
index 00000000000..53368e6dfab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-5.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=small -fno-PIC -mpc-relative-literal-loads -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	adrp	(x[0-9]+), \.LC0
+**	ldr	c0, \[\1, #:lo12:\.LC0\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro\.local,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-6.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-6.c
new file mode 100644
index 00000000000..7ed909424db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-6.c
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=small -fPIC -mpc-relative-literal-loads -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	adrp	(x[0-9]+), \.LC0
+**	ldr	c0, \[\1, #:lo12:\.LC0\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-7.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-7.c
new file mode 100644
index 00000000000..89ba1759861
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-7.c
@@ -0,0 +1,23 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=large -fno-PIC -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	adrp	(x[0-9]+), \.LC1
+**	ldr	(x[0-9]+), \[\1, #:lo12:\.LC1\]
+**	ldr	c0, \[\2\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.size\t\.LC1, 8\n\.LC1:\n\t\.xword\t\.LC0\n} } } */
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro\.local,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-8.c b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-8.c
new file mode 100644
index 00000000000..ef2129371c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/morello/hybrid-addr-expr-8.c
@@ -0,0 +1,22 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-mcmodel=large -fno-PIC -mpc-relative-literal-loads -fgimple -g0 -save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-mabi=purecap" "-mfake-capability" } { "" } }  */
+
+/*
+** foo:
+**	ldr	(x[0-9]+), \.LC1
+**	ldr	c0, \[\1\]
+**	ret
+*/
+int x;
+__GIMPLE int *__capability foo() {
+  int *__capability res;
+
+  res = __CAP_ADDR x;
+  return res;
+}
+
+/* { dg-final { scan-assembler {\t\.size\t\.LC1, 8\n\.LC1:\n\t\.xword\t\.LC0\n} } } */
+/* { dg-final { scan-assembler {\t\.section\t\.data\.rel\.ro\.local,"aw"\n\t\.align\t4\n\t\.type\t\.LC0, %object\n} } } */
+/* { dg-final { scan-assembler {\t\.size\t\.LC0, 16\n\.LC0:\n\t\.capinit\tx\n} } } */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-05 12:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-05 12:09 [gcc(refs/vendors/ARM/heads/morello)] aarch64: Hybrid support for non-TLS CADI symbols Matthew Malcomson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).