The varargs code for SVR4 puts all (integer) arguments in 4-byte slots. When it then reads an item from there as something not a multiple of 4 bytes, it needs to adjust the address if big endian. We didn't yet do that.
This fixes the g++.dg/abi/scoped1.C, gcc.dg/compat/scalar-by-value-4, and gcc.dg/compat/scalar-return-4 testcases. Bootstrapped and tested on powerpc64-linux {-m32,-m64}. Is this okay for trunk? Segher 2017-01-20 Segher Boessenkool <seg...@kernel.crashing.org> PR target/61729 PR target/77850 * config/rs6000/rs6000.c (rs6000_gimplify_va_arg): Adjust address to read from, for big endian. --- gcc/config/rs6000/rs6000.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index c5e65d3..381fbb6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -13685,6 +13685,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, size = int_size_in_bytes (type); rsize = (size + 3) / 4; + int pad = 4 * rsize - size; align = 1; machine_mode mode = TYPE_MODE (type); @@ -13766,6 +13767,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, && mode == SDmode) t = fold_build_pointer_plus_hwi (t, size); + /* Args are right-aligned. */ + if (BYTES_BIG_ENDIAN) + t = fold_build_pointer_plus_hwi (t, pad); + gimplify_assign (addr, t, pre_p); gimple_seq_add_stmt (pre_p, gimple_build_goto (lab_over)); @@ -13791,6 +13796,11 @@ rs6000_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_cst (TREE_TYPE (t), -align)); } + + /* Args are right-aligned. */ + if (BYTES_BIG_ENDIAN) + t = fold_build_pointer_plus_hwi (t, pad); + gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue); gimplify_assign (unshare_expr (addr), t, pre_p); -- 1.9.3