From a9a7993c26ad84f4ae2f45ce1da92d59f23d1ee8 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 1 Sep 2020 21:45:33 +0100 Subject: [PATCH] Generic : More mega-hack for va / normal. (cherry picked from commit 899ff6e14355886789586631c3eff9ab6f30fbfc) Signed-off-by: Kirill A. Korinsky --- gcc/calls.c | 6 ++++-- gcc/calls.h | 30 ++++++++++++++++++++++++++---- gcc/function.c | 27 ++++++++++++++++++++------- gcc/function.h | 2 +- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git gcc/calls.c gcc/calls.c index 3c0dff06bc5..e7bb0063381 100644 --- gcc/calls.c +++ gcc/calls.c @@ -2310,7 +2310,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, with those made by function.c. */ /* See if this argument should be passed by invisible reference. */ - function_arg_info arg (type, argpos < n_named_args); + function_arg_info arg (type, argpos < n_named_args, + argpos == n_named_args - 1); if (pass_by_reference (args_so_far_pnt, arg)) { const bool callee_copies @@ -2486,7 +2487,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, reg_parm_stack_space, args[i].pass_on_stack ? 0 : args[i].partial, fndecl, args_size, &args[i].locate, - argpos < n_named_args); + argpos < n_named_args, + argpos == n_named_args - 1); #ifdef BLOCK_REG_PADDING else /* The argument is passed entirely in registers. See at which diff --git gcc/calls.h gcc/calls.h index 4ee49360777..3c5fbad301a 100644 --- gcc/calls.h +++ gcc/calls.h @@ -35,24 +35,43 @@ class function_arg_info { public: function_arg_info () - : type (NULL_TREE), mode (VOIDmode), named (false), + : type (NULL_TREE), mode (VOIDmode), named (false), last_named (false), pass_by_reference (false) {} /* Initialize an argument of mode MODE, either before or after promotion. */ function_arg_info (machine_mode mode, bool named) - : type (NULL_TREE), mode (mode), named (named), pass_by_reference (false) + : type (NULL_TREE), mode (mode), named (named), last_named (false), + pass_by_reference (false) + {} + + function_arg_info (machine_mode mode, bool named, bool last_named) + : type (NULL_TREE), mode (mode), named (named), last_named (last_named), + pass_by_reference (false) {} /* Initialize an unpromoted argument of type TYPE. */ function_arg_info (tree type, bool named) - : type (type), mode (TYPE_MODE (type)), named (named), + : type (type), mode (TYPE_MODE (type)), named (named), last_named (false), pass_by_reference (false) {} + /* Initialize an unpromoted argument of type TYPE. */ + function_arg_info (tree type, bool named, bool last_named) + : type (type), mode (TYPE_MODE (type)), named (named), + last_named (last_named), pass_by_reference (false) + {} + /* Initialize an argument with explicit properties. */ function_arg_info (tree type, machine_mode mode, bool named) - : type (type), mode (mode), named (named), pass_by_reference (false) + : type (type), mode (mode), named (named), last_named (false), + pass_by_reference (false) + {} + + /* Initialize an argument with explicit properties. */ + function_arg_info (tree type, machine_mode mode, bool named, bool last_named) + : type (type), mode (mode), named (named), last_named (last_named), + pass_by_reference (false) {} /* Return true if the gimple-level type is an aggregate. */ @@ -105,6 +124,9 @@ public: "..."). See also TARGET_STRICT_ARGUMENT_NAMING. */ unsigned int named : 1; + /* True if this is the last named argument. */ + unsigned int last_named : 1; + /* True if we have decided to pass the argument by reference, in which case the function_arg_info describes a pointer to the original argument. */ unsigned int pass_by_reference : 1; diff --git gcc/function.c gcc/function.c index 1e4035074dc..4d5689057c6 100644 --- gcc/function.c +++ gcc/function.c @@ -2430,7 +2430,10 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, else if (DECL_CHAIN (parm)) data->arg.named = 1; /* Not the last non-variadic parm. */ else if (targetm.calls.strict_argument_naming (all->args_so_far)) - data->arg.named = 1; /* Only variadic ones are unnamed. */ + { + data->arg.named = 1; /* Only variadic ones are unnamed. */ + data->arg.last_named = 1; + } else data->arg.named = 0; /* Treat as variadic. */ @@ -2487,6 +2490,7 @@ assign_parms_setup_varargs (struct assign_parm_data_all *all, function_arg_info last_named_arg = data->arg; last_named_arg.named = true; + last_named_arg.last_named = true; targetm.calls.setup_incoming_varargs (all->args_so_far, last_named_arg, &varargs_pretend_bytes, no_rtl); @@ -2597,7 +2601,7 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all, all->reg_parm_stack_space, entry_parm ? data->partial : 0, current_function_decl, &all->stack_args_size, &data->locate, - data->arg.named); + data->arg.named, data->arg.last_named); /* Update parm_stack_boundary if this parameter is passed in the stack. */ @@ -3894,7 +3898,8 @@ gimplify_parameters (gimple_seq *cleanup) if (data.arg.pass_by_reference) { tree type = TREE_TYPE (data.arg.type); - function_arg_info orig_arg (type, data.arg.named); + function_arg_info orig_arg (type, data.arg.named, + data.arg.last_named); if (reference_callee_copied (&all.args_so_far_v, orig_arg)) { tree local, t; @@ -4001,7 +4006,7 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs, tree fndecl ATTRIBUTE_UNUSED, struct args_size *initial_offset_ptr, struct locate_and_pad_arg_data *locate, - bool named_p) + bool named_p, bool last_named_p) { tree sizetree; pad_direction where_pad; @@ -4038,10 +4043,18 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs, where_pad = targetm.calls.function_arg_padding (passed_mode, type); boundary = targetm.calls.function_arg_boundary (passed_mode, type); if (named_p) - round_boundary = targetm.calls.function_arg_round_boundary (passed_mode, - type); + { + round_boundary = targetm.calls.function_arg_round_boundary (passed_mode, + type); + if (last_named_p) + round_boundary = PARM_BOUNDARY; + } else - round_boundary = PARM_BOUNDARY; + { + /* Force everything to be at least aligned to the parm boundary. */ + boundary = MAX (boundary, PARM_BOUNDARY); + round_boundary = PARM_BOUNDARY; + } locate->where_pad = where_pad; diff --git gcc/function.h gcc/function.h index 412509af923..faa3135a766 100644 --- gcc/function.h +++ gcc/function.h @@ -646,7 +646,7 @@ 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 *, - bool named_p = true); + bool named_p = true, bool last_named = false); extern void generate_setjmp_warnings (void); /* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END}, -- 2.42.1