View | Details | Raw Unified | Return to bug 77728 | Differences between
and this patch

Collapse All | Expand All

(-)gcc/config/aarch64/aarch64.c.jj (-25 / +70 lines)
Lines 2256-2288 aarch64_vfp_is_call_candidate (cumulativ Link Here
2256
						  NULL);
2256
						  NULL);
2257
}
2257
}
2258
2258
2259
/* Given MODE and TYPE of a function argument, return the alignment in
2259
struct aarch64_fn_arg_alignment
2260
{
2261
  /* Alignment for FIELD_DECLs in function arguments.  */
2262
  unsigned int alignment;
2263
  /* Alignment for decls other than FIELD_DECLs in function arguments.  */
2264
  unsigned int warn_alignment;
2265
};
2266
2267
/* Given MODE and TYPE of a function argument, return a pair of alignments in
2260
   bits.  The idea is to suppress any stronger alignment requested by
2268
   bits.  The idea is to suppress any stronger alignment requested by
2261
   the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
2269
   the user and opt for the natural alignment (specified in AAPCS64 \S 4.1).
2262
   This is a helper function for local use only.  */
2270
   This is a helper function for local use only.  */
2263
2271
2264
static unsigned int
2272
static struct aarch64_fn_arg_alignment
2265
aarch64_function_arg_alignment (machine_mode mode, const_tree type)
2273
aarch64_function_arg_alignment (machine_mode mode, const_tree type)
2266
{
2274
{
2275
  struct aarch64_fn_arg_alignment aa;
2276
  aa.alignment = 0;
2277
  aa.warn_alignment = 0;
2278
2267
  if (!type)
2279
  if (!type)
2268
    return GET_MODE_ALIGNMENT (mode);
2280
    {
2281
      aa.alignment = GET_MODE_ALIGNMENT (mode);
2282
      return aa;
2283
    }
2284
2269
  if (integer_zerop (TYPE_SIZE (type)))
2285
  if (integer_zerop (TYPE_SIZE (type)))
2270
    return 0;
2286
    return aa;
2271
2287
2272
  gcc_assert (TYPE_MODE (type) == mode);
2288
  gcc_assert (TYPE_MODE (type) == mode);
2273
2289
2274
  if (!AGGREGATE_TYPE_P (type))
2290
  if (!AGGREGATE_TYPE_P (type))
2275
    return TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
2291
    {
2292
      aa.alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type));
2293
      return aa;
2294
    }
2276
2295
2277
  if (TREE_CODE (type) == ARRAY_TYPE)
2296
  if (TREE_CODE (type) == ARRAY_TYPE)
2278
    return TYPE_ALIGN (TREE_TYPE (type));
2297
    {
2279
2298
      aa.alignment = TYPE_ALIGN (TREE_TYPE (type));
2280
  unsigned int alignment = 0;
2299
      return aa;
2300
    }
2281
2301
2282
  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
2302
  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
2283
    alignment = std::max (alignment, DECL_ALIGN (field));
2303
    {
2304
      if (TREE_CODE (field) == FIELD_DECL)
2305
	aa.alignment = std::max (aa.alignment, DECL_ALIGN (field));
2306
      else
2307
	aa.warn_alignment = std::max (aa.warn_alignment, DECL_ALIGN (field));
2308
    }
2284
2309
2285
  return alignment;
2310
  return aa;
2286
}
2311
}
2287
2312
2288
/* Layout a function argument according to the AAPCS64 rules.  The rule
2313
/* Layout a function argument according to the AAPCS64 rules.  The rule
Lines 2369-2392 aarch64_layout_arg (cumulative_args_t pc Link Here
2369
     entirely general registers.  */
2394
     entirely general registers.  */
2370
  if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS))
2395
  if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS))
2371
    {
2396
    {
2372
      unsigned int alignment = aarch64_function_arg_alignment (mode, type);
2373
2397
2374
      gcc_assert (nregs == 0 || nregs == 1 || nregs == 2);
2398
      gcc_assert (nregs == 0 || nregs == 1 || nregs == 2);
2375
2399
2376
      /* C.8 if the argument has an alignment of 16 then the NGRN is
2400
      /* C.8 if the argument has an alignment of 16 then the NGRN is
2377
         rounded up to the next even number.  */
2401
         rounded up to the next even number.  */
2378
      if (nregs == 2 && alignment == 16 * BITS_PER_UNIT && ncrn % 2)
2402
      if (nregs == 2 && ncrn % 2)
2379
	{
2403
	{
2380
	  ++ncrn;
2404
	  struct aarch64_fn_arg_alignment aa
2381
	  gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
2405
	    = aarch64_function_arg_alignment (mode, type);
2406
2407
	  if (aa.warn_alignment == 16 * BITS_PER_UNIT
2408
	      && aa.alignment < aa.warn_alignment
2409
	      && warn_psabi
2410
	      && currently_expanding_gimple_stmt)
2411
	    inform (input_location,
2412
		    "parameter passing for argument of type %qT "
2413
		    "changed in GCC 7.1", type);
2414
	  else if (aa.alignment == 16 * BITS_PER_UNIT)
2415
	    {
2416
	      ++ncrn;
2417
	      gcc_assert (ncrn + nregs <= NUM_ARG_REGS);
2418
	    }
2382
	}
2419
	}
2420
2383
      /* NREGS can be 0 when e.g. an empty structure is to be passed.
2421
      /* NREGS can be 0 when e.g. an empty structure is to be passed.
2384
         A reg is still generated for it, but the caller should be smart
2422
         A reg is still generated for it, but the caller should be smart
2385
	 enough not to use it.  */
2423
	 enough not to use it.  */
2386
      if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT)
2424
      if (nregs == 0 || nregs == 1 || GET_MODE_CLASS (mode) == MODE_INT)
2387
	{
2425
	pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn);
2388
	  pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn);
2389
	}
2390
      else
2426
      else
2391
	{
2427
	{
2392
	  rtx par;
2428
	  rtx par;
Lines 2414-2420 aarch64_layout_arg (cumulative_args_t pc Link Here
2414
     this argument and align the total size if necessary.  */
2450
     this argument and align the total size if necessary.  */
2415
on_stack:
2451
on_stack:
2416
  pcum->aapcs_stack_words = size / UNITS_PER_WORD;
2452
  pcum->aapcs_stack_words = size / UNITS_PER_WORD;
2417
  if (aarch64_function_arg_alignment (mode, type) == 16 * BITS_PER_UNIT)
2453
  struct aarch64_fn_arg_alignment aa
2454
    = aarch64_function_arg_alignment (mode, type);
2455
2456
  if (aa.alignment == 16 * BITS_PER_UNIT)
2418
    pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size,
2457
    pcum->aapcs_stack_size = ROUND_UP (pcum->aapcs_stack_size,
2419
				       16 / UNITS_PER_WORD);
2458
				       16 / UNITS_PER_WORD);
2420
  return;
2459
  return;
Lines 2505-2517 aarch64_function_arg_regno_p (unsigned r Link Here
2505
static unsigned int
2544
static unsigned int
2506
aarch64_function_arg_boundary (machine_mode mode, const_tree type)
2545
aarch64_function_arg_boundary (machine_mode mode, const_tree type)
2507
{
2546
{
2508
  unsigned int alignment = aarch64_function_arg_alignment (mode, type);
2547
  struct aarch64_fn_arg_alignment aa
2548
    = aarch64_function_arg_alignment (mode, type);
2549
  aa.alignment = MIN (MAX (aa.alignment, PARM_BOUNDARY), STACK_BOUNDARY);
2550
  aa.warn_alignment
2551
    = MIN (MAX (aa.warn_alignment, PARM_BOUNDARY), STACK_BOUNDARY);
2552
2553
  if (warn_psabi && aa.warn_alignment > aa.alignment)
2554
    inform (input_location, "parameter passing for argument of type %qT "
2555
	    "changed in GCC 7.1", type);
2509
2556
2510
  if (alignment < PARM_BOUNDARY)
2557
  return aa.alignment;
2511
    alignment = PARM_BOUNDARY;
2512
  if (alignment > STACK_BOUNDARY)
2513
    alignment = STACK_BOUNDARY;
2514
  return alignment;
2515
}
2558
}
2516
2559
2517
/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
2560
/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
Lines 10211-10217 aarch64_gimplify_va_arg_expr (tree valis Link Here
10211
  stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist),
10254
  stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist),
10212
		  f_stack, NULL_TREE);
10255
		  f_stack, NULL_TREE);
10213
  size = int_size_in_bytes (type);
10256
  size = int_size_in_bytes (type);
10214
  align = aarch64_function_arg_alignment (mode, type) / BITS_PER_UNIT;
10257
  struct aarch64_fn_arg_alignment aa
10258
    = aarch64_function_arg_alignment (mode, type);
10259
  align = aa.alignment / BITS_PER_UNIT;
10215
10260
10216
  dw_align = false;
10261
  dw_align = false;
10217
  adjust = 0;
10262
  adjust = 0;
(-)gcc/testsuite/g++.dg/abi/pr77728-2.C.jj (+171 lines)
Line 0 Link Here
1
// { dg-do compile { target { { aarch64-*-* } && c++11 } } }
2
// { dg-options "-Wpsabi" }
3
4
#include <stdarg.h>
5
6
template <int N>
7
struct alignas (16) A { char p[16]; };
8
9
A<0> v;
10
11
template <int N>
12
struct B
13
{
14
  typedef A<N> T;
15
  int i, j, k, l;
16
};
17
18
struct C : public B<0> {};
19
struct D {};
20
struct E : public D, C {};
21
struct F : public B<1> {};
22
struct G : public F { static int y alignas (16); };
23
struct H : public G {};
24
struct I : public D { int z alignas (16); };
25
struct J : public D { static int z alignas (16); int i, j, k, l; };
26
27
template <int N>
28
struct K : public D { typedef A<N> T; int i, j; };
29
30
struct L { static int h alignas (16); int i, j, k, l; };
31
32
int
33
fn1 (int a, B<0> b)	// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
34
{
35
  return a + b.i;
36
}
37
38
int
39
fn2 (int a, B<1> b)
40
{
41
  return a + b.i;
42
}
43
44
int
45
fn3 (int a, L b)	// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
46
{
47
  return a + b.i;
48
}
49
50
int
51
fn4 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<0> n, ...)
52
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
53
{
54
  va_list ap;
55
  va_start (ap, n);
56
  int x = va_arg (ap, int);
57
  va_end (ap);
58
  return x;
59
}
60
61
int
62
fn5 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<1> n, ...)
63
{
64
  va_list ap;
65
  va_start (ap, n);
66
  int x = va_arg (ap, int);
67
  va_end (ap);
68
  return x;
69
}
70
71
int
72
fn6 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, C n, ...)
73
{
74
  va_list ap;
75
  va_start (ap, n);
76
  int x = va_arg (ap, int);
77
  va_end (ap);
78
  return x;
79
}
80
81
int
82
fn7 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, E n, ...)
83
{
84
  va_list ap;
85
  va_start (ap, n);
86
  int x = va_arg (ap, int);
87
  va_end (ap);
88
  return x;
89
}
90
91
int
92
fn8 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, H n, ...)
93
{
94
  va_list ap;
95
  va_start (ap, n);
96
  int x = va_arg (ap, int);
97
  va_end (ap);
98
  return x;
99
}
100
101
int
102
fn9 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, I n, ...)
103
{
104
  va_list ap;
105
  va_start (ap, n);
106
  int x = va_arg (ap, int);
107
  va_end (ap);
108
  return x;
109
}
110
111
int
112
fn10 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, J n, ...)
113
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
114
{
115
  va_list ap;
116
  va_start (ap, n);
117
  int x = va_arg (ap, int);
118
  va_end (ap);
119
  return x;
120
}
121
122
int
123
fn11 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<0> n, ...)
124
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
125
{
126
  va_list ap;
127
  va_start (ap, n);
128
  int x = va_arg (ap, int);
129
  va_end (ap);
130
  return x;
131
}
132
133
int
134
fn12 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<2> n, ...)
135
{
136
  va_list ap;
137
  va_start (ap, n);
138
  int x = va_arg (ap, int);
139
  va_end (ap);
140
  return x;
141
}
142
143
void
144
test ()
145
{
146
  static B<0> b0;
147
  static B<1> b1;
148
  static L l;
149
  static C c;
150
  static E e;
151
  static H h;
152
  static I i;
153
  static J j;
154
  static K<0> k0;
155
  static K<2> k2;
156
  fn1 (1, b0);	// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
157
  fn2 (1, b1);
158
  fn3 (1, l);	// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
159
  fn4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b0, 1, 2, 3, 4);
160
  // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
161
  fn5 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b1, 1, 2, 3, 4);
162
  fn6 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, c, 1, 2, 3, 4);
163
  fn7 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, e, 1, 2, 3, 4);
164
  fn8 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, h, 1, 2, 3, 4);
165
  fn9 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, i, 1, 2, 3, 4);
166
  fn10 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, j, 1, 2, 3, 4);
167
  // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
168
  fn11 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k0, 1, 2, 3, 4);
169
  // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
170
  fn12 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k2, 1, 2, 3, 4);
171
}

Return to bug 77728