public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/morello)] morello: Outgoing stack layout for new varargs PCS
@ 2021-12-10 16:49 Matthew Malcomson
  0 siblings, 0 replies; only message in thread
From: Matthew Malcomson @ 2021-12-10 16:49 UTC (permalink / raw)
  To: gcc-cvs

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

commit c03e6907c735ef4c8aa98f6fed4ca3e3ce9eef1b
Author: Alex Coplan <alex.coplan@arm.com>
Date:   Fri Oct 29 14:56:34 2021 +0100

    morello: Outgoing stack layout for new varargs PCS
    
    This implements the stack layout for the outgoing side of the new Morello
    varargs PCS (https://github.com/ARM-software/abi-aa/pull/112).
    
    Rule C.1 says:
    
    If the argument is Anonymous in AAPCS64-cap and its size is less than 16
    bytes, the size of the argument is set to 16 bytes. The effect is as if
    the argument was copied to the least significant bits of a 128-bit
    register and the remaining bits filled with unspecified values.
    
    To achieve this, we modify aarch64_function_arg_boundary to round up to
    16 * BITS_PER_UNIT for anonymous arguments. Prior to this change, the
    function_arg_boundary hook was purely a function of the mode and type of
    the argument. In order to implement rule C.1 above, we extend this hook
    to also take a boolean which says whether the argument is named or not.
    
    This patch is sufficient to get the correct stack layout for the
    outgoing arguments, but does not set up a capability to the Anonymous
    Argument Memory Area in c9. This will be done in the next patch in the
    series.
    
    There will need to be a follow-on patch to fix up the build for
    non-AArch64 targets w.r.t. the target hook change, but this is not an
    immediate priority.
    
    gcc/ChangeLog:
    
            * calls.c (initialize_argument_information): Pass arg.named
            through to locate_and_pad_parm.
            (emit_library_call_value_1): Likewise.
            * config/aarch64/aarch64.c (aarch64_pass_by_reference_1):
            Implement new PCS rules B.2 and B.3.
            (aarch64_layout_arg): Implement new PCS rules C.1 and C.2.
            (aarch64_function_arg_boundary): Implement new PCS rule C.1.
            * doc/tm.texi: Regenerate.
            * function.c (assign_parm_find_entry_rtl): Pass named parameter
            through to locate_and_pad_parm.
            (assign_parms): Pass named parameter to function_arg_boundary
            hook.
            (locate_and_pad_parm): Add named parameter, pass through to
            function_arg_boundary hook.
            * function.h (locate_and_pad_parm): Add named parameter.
            * target.def (function_arg_boundary): Likewise.
            * targhooks.c (std_gimplify_va_arg_expr): Pass false for new
            named parameter.

Diff:
---
 gcc/calls.c                  |  9 ++++--
 gcc/config/aarch64/aarch64.c | 71 ++++++++++++++++++++++++++++++++++----------
 gcc/doc/tm.texi              |  2 +-
 gcc/function.c               | 11 ++++---
 gcc/function.h               |  3 +-
 gcc/target.def               |  2 +-
 gcc/targhooks.c              |  3 +-
 7 files changed, 74 insertions(+), 27 deletions(-)

diff --git a/gcc/calls.c b/gcc/calls.c
index 5f6aa9d62a3..8d002bc415a 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -2423,7 +2423,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 #endif
 			     reg_parm_stack_space,
 			     args[i].pass_on_stack ? 0 : args[i].partial,
-			     fndecl, args_size, &args[i].locate);
+			     fndecl, args_size, &args[i].locate,
+			     arg.named);
 #ifdef BLOCK_REG_PADDING
       else
 	/* The argument is passed entirely in registers.  See at which
@@ -5153,7 +5154,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 			   argvec[count].reg != 0,
 #endif
 			   reg_parm_stack_space, 0,
-			   NULL_TREE, &args_size, &argvec[count].locate);
+			   NULL_TREE, &args_size, &argvec[count].locate,
+			   ptr_arg.named);
 
       if (argvec[count].reg == 0 || argvec[count].partial != 0
 	  || reg_parm_stack_space > 0)
@@ -5244,7 +5246,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 			       argvec[count].reg != 0,
 #endif
 			       reg_parm_stack_space, argvec[count].partial,
-			       NULL_TREE, &args_size, &argvec[count].locate);
+			       NULL_TREE, &args_size, &argvec[count].locate,
+			       arg.named);
 	  args_size.constant += argvec[count].locate.size.constant;
 	  gcc_assert (!argvec[count].locate.size.var);
 	}
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3575714d01e..39b8d738c0b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -5846,11 +5846,14 @@ aarch64_pass_by_reference_1 (CUMULATIVE_ARGS *pcum,
        shouldn't be asked to pass or return them.  */
     size = GET_MODE_SIZE (arg.mode).to_constant ();
 
+  capability_composite_type capcom = CAPCOM_NONE;
+
   /* Aggregates are passed by reference based on their size.  */
   if (arg.aggregate_type_p ())
     {
       size = int_size_in_bytes (arg.type);
-      switch (aarch64_classify_capability_contents (arg.type))
+      capcom = aarch64_classify_capability_contents (arg.type);
+      switch (capcom)
 	{
 	case CAPCOM_NONE:
 	case CAPCOM_LARGE:
@@ -5869,6 +5872,24 @@ aarch64_pass_by_reference_1 (CUMULATIVE_ARGS *pcum,
   if (size < 0)
     return true;
 
+  /* Morello B.2 If the argument is anonymous in AAPCS64-cap and the size or
+     alignment of the argument is larger than 16, the argument is copied
+     to memory and the argument is replaced by a capability to the copy.  */
+  if (TARGET_CAPABILITY_PURE
+      && !arg.named
+      && ((size > 16)
+	  || (arg.type && TYPE_ALIGN (arg.type) > (16 * BITS_PER_UNIT))))
+    return true;
+
+  /* Morello B.3 If the argument is anonymous in AAPCS64 and the argument type
+     is a capability or the argument type is a Composite Type which contains
+     capabilities, the argument is copied to memory and the argument is replaced
+     by a pointer to the copy.  */
+  if (TARGET_CAPABILITY_HYBRID
+      && arg.type
+      && (capability_type_p (arg.type) || capcom == CAPCOM_SOME))
+    return true;
+
   /* Can this be a candidate to be passed in fp/simd register(s)?  */
   if (aarch64_vfp_is_call_or_return_candidate (arg.mode, arg.type,
 					       &dummymode, &nregs, NULL,
@@ -6260,10 +6281,12 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
   tree type = arg.type;
   machine_mode mode = arg.mode;
   int ncrn, nvrn, nregs;
+  unsigned vec_flags;
   bool allocate_ncrn, allocate_nvrn;
   HOST_WIDE_INT size, units_per_reg = UNITS_PER_WORD;
-  bool abi_break;
+  bool abi_break, sve_p;
   bool in_cap_regs = false;
+  pure_scalable_type_info pst_info;
 
   /* We need to do this once per argument.  */
   if (pcum->aapcs_arg_processed)
@@ -6271,7 +6294,29 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 
   pcum->aapcs_arg_processed = true;
 
-  pure_scalable_type_info pst_info;
+  /* Size in bytes, rounded to the nearest multiple of 8 bytes.  */
+  if (type)
+    size = int_size_in_bytes (type);
+  else
+    /* No frontends can create types with variable-sized modes, so we
+       shouldn't be asked to pass or return them.  */
+    size = GET_MODE_SIZE (mode).to_constant ();
+  HOST_WIDE_INT orig_size = size;
+  size = ROUND_UP (size, UNITS_PER_WORD);
+
+  if (TARGET_CAPABILITY_PURE && !arg.named)
+    {
+      /* Morello C.1 If the argument is Anonymous in AAPCS64-cap and its size is
+	 less than 16 bytes, the size of the argument is set to 16 bytes.
+
+	 Morello C.2 If the argument is Anonymous in AAPCS64-cap the argument is
+	 copied to memory at an offset of (AArgsIdx * 16) into the Anonymous
+	 Argument Memory area.  */
+      gcc_assert (size <= 16);
+      size = 16;
+      goto on_stack;
+    }
+
   if (type && pst_info.analyze_registers (type))
     {
       /* The PCS says that it is invalid to pass an SVE value to an
@@ -6303,8 +6348,8 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 
   /* Generic vectors that map to full SVE modes with -msve-vector-bits=N
      are passed by reference, not by value.  */
-  unsigned int vec_flags = aarch64_classify_vector_mode (mode);
-  bool sve_p = (vec_flags & VEC_ANY_SVE);
+  vec_flags = aarch64_classify_vector_mode (mode);
+  sve_p = (vec_flags & VEC_ANY_SVE);
   if (sve_p)
     /* Vector types can acquire a partial SVE mode using things like
        __attribute__((vector_size(N))), and this is potentially useful.
@@ -6319,16 +6364,6 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 		&& (aarch64_some_values_include_pst_objects_p (type)
 		    || (vec_flags & VEC_PARTIAL)));
 
-  /* Size in bytes, rounded to the nearest multiple of 8 bytes.  */
-  if (type)
-    size = int_size_in_bytes (type);
-  else
-    /* No frontends can create types with variable-sized modes, so we
-       shouldn't be asked to pass or return them.  */
-    size = GET_MODE_SIZE (mode).to_constant ();
-  HOST_WIDE_INT orig_size = size;
-  size = ROUND_UP (size, UNITS_PER_WORD);
-
   allocate_ncrn = (type) ? !(FLOAT_TYPE_P (type)) : !FLOAT_MODE_P (mode);
   allocate_nvrn = aarch64_vfp_is_call_candidate (pcum_v,
 						 mode,
@@ -6639,7 +6674,8 @@ aarch64_function_arg_regno_p (unsigned regno)
    8 bytes.  */
 
 static unsigned int
-aarch64_function_arg_boundary (machine_mode mode, const_tree type)
+aarch64_function_arg_boundary (machine_mode mode, const_tree type,
+			       bool named)
 {
   bool abi_break;
   unsigned int alignment = aarch64_function_arg_alignment (mode, type,
@@ -6648,6 +6684,9 @@ aarch64_function_arg_boundary (machine_mode mode, const_tree type)
     inform (input_location, "parameter passing for argument of type "
 	    "%qT changed in GCC 9.1", type);
 
+  if (TARGET_CAPABILITY_PURE && !named)
+    alignment = MAX (16 * BITS_PER_UNIT, alignment);
+
   return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
 }
 
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 6670eb420e9..ec91a9dac66 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4268,7 +4268,7 @@ a three byte aggregate may be passed in the high part of a register if so
 required.
 @end defmac
 
-@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_BOUNDARY (machine_mode @var{mode}, const_tree @var{type})
+@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_BOUNDARY (machine_mode @var{mode}, const_tree @var{type}, bool @var{named})
 This hook returns the alignment boundary, in bits, of an argument
 with the specified mode and type.  The default hook returns
 @code{PARM_BOUNDARY} for all arguments.
diff --git a/gcc/function.c b/gcc/function.c
index d4e49bc1988..8fb6a4cfb27 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2601,7 +2601,8 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
   locate_and_pad_parm (data->arg.mode, data->arg.type, in_regs,
 		       all->reg_parm_stack_space,
 		       entry_parm ? data->partial : 0, current_function_decl,
-		       &all->stack_args_size, &data->locate);
+		       &all->stack_args_size, &data->locate,
+		       data->arg.named);
 
   /* Update parm_stack_boundary if this parameter is passed in the
      stack.  */
@@ -3637,7 +3638,8 @@ assign_parms (tree fndecl)
         {
           unsigned int align
 	    = targetm.calls.function_arg_boundary (data.arg.mode,
-						   data.arg.type);
+						   data.arg.type,
+						   data.arg.named);
 	  align = MINIMUM_ALIGNMENT (data.arg.type, data.arg.mode, align);
 	  if (TYPE_ALIGN (data.nominal_type) > align)
 	    align = MINIMUM_ALIGNMENT (data.nominal_type,
@@ -4003,7 +4005,8 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
 		     int reg_parm_stack_space, int partial,
 		     tree fndecl ATTRIBUTE_UNUSED,
 		     struct args_size *initial_offset_ptr,
-		     struct locate_and_pad_arg_data *locate)
+		     struct locate_and_pad_arg_data *locate,
+		     bool named)
 {
   tree sizetree;
   pad_direction where_pad;
@@ -4038,7 +4041,7 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
 	      ? arg_size_in_bytes (type)
 	      : size_int (GET_MODE_SIZE (passed_mode)));
   where_pad = targetm.calls.function_arg_padding (passed_mode, type);
-  boundary = targetm.calls.function_arg_boundary (passed_mode, type);
+  boundary = targetm.calls.function_arg_boundary (passed_mode, type, named);
   round_boundary = targetm.calls.function_arg_round_boundary (passed_mode,
 							      type);
   locate->where_pad = where_pad;
diff --git a/gcc/function.h b/gcc/function.h
index 661b40977ad..ca7fee7e83b 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -648,7 +648,8 @@ extern bool use_register_for_decl (const_tree);
 extern gimple_seq gimplify_parameters (gimple_seq *);
 extern void locate_and_pad_parm (machine_mode, tree, int, int, int,
 				 tree, struct args_size *,
-				 struct locate_and_pad_arg_data *);
+				 struct locate_and_pad_arg_data *,
+				 bool named);
 extern void generate_setjmp_warnings (void);
 
 /* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
diff --git a/gcc/target.def b/gcc/target.def
index b450354ab23..67bab12f9b2 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5003,7 +5003,7 @@ DEFHOOK
  "This hook returns the alignment boundary, in bits, of an argument\n\
 with the specified mode and type.  The default hook returns\n\
 @code{PARM_BOUNDARY} for all arguments.",
- unsigned int, (machine_mode mode, const_tree type),
+ unsigned int, (machine_mode mode, const_tree type, bool named),
  default_function_arg_boundary)
 
 DEFHOOK
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 3b812a2b98b..60059a5bc93 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2208,7 +2208,8 @@ std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
    }
 
   align = PARM_BOUNDARY / BITS_PER_UNIT;
-  boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
+  boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type,
+						  false);
 
   /* When we align parameter on stack for caller, if the parameter
      alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be


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

only message in thread, other threads:[~2021-12-10 16:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-10 16:49 [gcc(refs/vendors/ARM/heads/morello)] morello: Outgoing stack layout for new varargs PCS 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).