This patch updates assign_parm_find_data_types to assign passed_mode and nominal_mode with the mode of the built pointer type instead of the hard-coded Pmode in the case of pass-by-reference. This is in line with the assignment to passed_mode and nominal_mode in other cases inside the function.

assign_parm_find_data_types generally uses TYPE_MODE to calculate passed_mode and nominal_mode:

  /* Find mode of arg as it is passed, and mode of arg as it should be
     during execution of this function.  */
  passed_mode = TYPE_MODE (passed_type);
  nominal_mode = TYPE_MODE (nominal_type);

this includes the case when the passed argument is a pointer by itself.

However there is a discrepancy when it deals with argument passed by invisible reference; it builds the argument's corresponding pointer type, but sets passed_mode and nominal_mode with Pmode directly.

This is OK for targets where Pmode == ptr_mode, but on AArch64 with ILP32 they are different with Pmode as DImode and ptr_mode as SImode. When such a reference is passed on stack, the reference is prepared by the caller in the lower 4 bytes of an 8-byte slot but is fetched by the callee as an 8-byte datum, of which the higher 4 bytes may contain junk. It is probably the combination of Pmode != ptr_mode and the particular ABI specification that make the AArch64 ILP32 the first target on which the issue manifests itself.

Bootstrapped on x86_64-none-linux-gnu.

OK for the trunk?

Thanks,
Yufeng


gcc/
        * function.c (assign_parm_find_data_types): Set passed_mode and
        nominal_mode to the TYPE_MODE of nominal_type for the built
        pointer type in case of the struct-pass-by-reference.
diff --git a/gcc/function.c b/gcc/function.c
index 3e33fc7..6a0aaaf 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2369,7 +2369,7 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
     {
       passed_type = nominal_type = build_pointer_type (passed_type);
       data->passed_pointer = true;
-      passed_mode = nominal_mode = Pmode;
+      passed_mode = nominal_mode = TYPE_MODE (nominal_type);
     }
 
   /* Find mode as it is passed by the ABI.  */

Reply via email to