|
|
745403 |
2019-05-29 Jakub Jelinek <jakub@redhat.com>
|
|
|
745403 |
|
|
|
745403 |
PR fortran/90329
|
|
|
745403 |
* lto-streamer.h (LTO_minor_version): Bump to 2.
|
|
|
745403 |
|
|
|
745403 |
Backported from mainline
|
|
|
745403 |
2019-05-16 Jakub Jelinek <jakub@redhat.com>
|
|
|
745403 |
|
|
|
745403 |
PR fortran/90329
|
|
|
745403 |
* tree-core.h (struct tree_decl_common): Document
|
|
|
745403 |
decl_nonshareable_flag for PARM_DECLs.
|
|
|
745403 |
* tree.h (DECL_HIDDEN_STRING_LENGTH): Define.
|
|
|
745403 |
* calls.c (expand_call): Don't try tail call if caller
|
|
|
745403 |
has any DECL_HIDDEN_STRING_LENGTH PARM_DECLs that are or might be
|
|
|
745403 |
passed on the stack and callee needs to pass any arguments on the
|
|
|
745403 |
stack.
|
|
|
745403 |
* tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use
|
|
|
745403 |
else if instead of series of mutually exclusive ifs. Handle
|
|
|
745403 |
DECL_HIDDEN_STRING_LENGTH for PARM_DECLs.
|
|
|
745403 |
* tree-streamer-out.c (pack_ts_decl_common_value_fields): Likewise.
|
|
|
745403 |
|
|
|
745403 |
* lang.opt (fbroken-callers): Remove.
|
|
|
745403 |
(ftail-call-workaround, ftail-call-workaround=): New options.
|
|
|
745403 |
* gfortran.h (struct gfc_namespace): Add implicit_interface_calls.
|
|
|
745403 |
* interface.c (gfc_procedure_use): Set implicit_interface_calls
|
|
|
745403 |
for calls to implicit interface procedures.
|
|
|
745403 |
* trans-decl.c (create_function_arglist): Use flag_tail_call_workaround
|
|
|
745403 |
instead of flag_broken_callers. If it is not 2, also require
|
|
|
745403 |
sym->ns->implicit_interface_calls.
|
|
|
745403 |
* invoke.texi (fbroken-callers): Remove documentation.
|
|
|
745403 |
(ftail-call-workaround, ftail-call-workaround=): Document.
|
|
|
745403 |
|
|
|
745403 |
2019-05-19 Thomas Koenig <tkoenig@gcc.gnu.org>
|
|
|
745403 |
|
|
|
745403 |
PR fortran/90329
|
|
|
745403 |
* invoke.texi: Document -fbroken-callers.
|
|
|
745403 |
* lang.opt: Add -fbroken-callers.
|
|
|
745403 |
* trans-decl.c (create_function_arglist): Only set
|
|
|
745403 |
DECL_HIDDEN_STRING_LENGTH if flag_broken_callers is set.
|
|
|
745403 |
|
|
|
745403 |
2019-05-16 Jakub Jelinek <jakub@redhat.com>
|
|
|
745403 |
|
|
|
745403 |
PR fortran/90329
|
|
|
745403 |
* trans-decl.c (create_function_arglist): Set
|
|
|
745403 |
DECL_HIDDEN_STRING_LENGTH on hidden string length PARM_DECLs if
|
|
|
745403 |
len is constant.
|
|
|
745403 |
|
|
|
745403 |
--- gcc/calls.c
|
|
|
745403 |
+++ gcc/calls.c
|
|
|
745403 |
@@ -3754,6 +3754,28 @@ expand_call (tree exp, rtx target, int ignore)
|
|
|
745403 |
|| dbg_cnt (tail_call) == false)
|
|
|
745403 |
try_tail_call = 0;
|
|
|
745403 |
|
|
|
745403 |
+ /* Workaround buggy C/C++ wrappers around Fortran routines with
|
|
|
745403 |
+ character(len=constant) arguments if the hidden string length arguments
|
|
|
745403 |
+ are passed on the stack; if the callers forget to pass those arguments,
|
|
|
745403 |
+ attempting to tail call in such routines leads to stack corruption.
|
|
|
745403 |
+ Avoid tail calls in functions where at least one such hidden string
|
|
|
745403 |
+ length argument is passed (partially or fully) on the stack in the
|
|
|
745403 |
+ caller and the callee needs to pass any arguments on the stack.
|
|
|
745403 |
+ See PR90329. */
|
|
|
745403 |
+ if (try_tail_call && maybe_ne (args_size.constant, 0))
|
|
|
745403 |
+ for (tree arg = DECL_ARGUMENTS (current_function_decl);
|
|
|
745403 |
+ arg; arg = DECL_CHAIN (arg))
|
|
|
745403 |
+ if (DECL_HIDDEN_STRING_LENGTH (arg) && DECL_INCOMING_RTL (arg))
|
|
|
745403 |
+ {
|
|
|
745403 |
+ subrtx_iterator::array_type array;
|
|
|
745403 |
+ FOR_EACH_SUBRTX (iter, array, DECL_INCOMING_RTL (arg), NONCONST)
|
|
|
745403 |
+ if (MEM_P (*iter))
|
|
|
745403 |
+ {
|
|
|
745403 |
+ try_tail_call = 0;
|
|
|
745403 |
+ break;
|
|
|
745403 |
+ }
|
|
|
745403 |
+ }
|
|
|
745403 |
+
|
|
|
745403 |
/* If the user has marked the function as requiring tail-call
|
|
|
745403 |
optimization, attempt it. */
|
|
|
745403 |
if (must_tail_call)
|
|
|
745403 |
--- gcc/fortran/gfortran.h
|
|
|
745403 |
+++ gcc/fortran/gfortran.h
|
|
|
745403 |
@@ -1857,6 +1857,9 @@ typedef struct gfc_namespace
|
|
|
745403 |
|
|
|
745403 |
/* Set to 1 for !$ACC ROUTINE namespaces. */
|
|
|
745403 |
unsigned oacc_routine:1;
|
|
|
745403 |
+
|
|
|
745403 |
+ /* Set to 1 if there are any calls to procedures with implicit interface. */
|
|
|
745403 |
+ unsigned implicit_interface_calls:1;
|
|
|
745403 |
}
|
|
|
745403 |
gfc_namespace;
|
|
|
745403 |
|
|
|
745403 |
--- gcc/fortran/interface.c
|
|
|
745403 |
+++ gcc/fortran/interface.c
|
|
|
745403 |
@@ -3657,6 +3657,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
|
|
|
745403 |
gfc_warning (OPT_Wimplicit_procedure,
|
|
|
745403 |
"Procedure %qs called at %L is not explicitly declared",
|
|
|
745403 |
sym->name, where);
|
|
|
745403 |
+ gfc_find_proc_namespace (sym->ns)->implicit_interface_calls = 1;
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
if (sym->attr.if_source == IFSRC_UNKNOWN)
|
|
|
745403 |
--- gcc/fortran/invoke.texi
|
|
|
745403 |
+++ gcc/fortran/invoke.texi
|
|
|
745403 |
@@ -181,7 +181,8 @@ and warnings}.
|
|
|
745403 |
@item Code Generation Options
|
|
|
745403 |
@xref{Code Gen Options,,Options for code generation conventions}.
|
|
|
745403 |
@gccoptlist{-faggressive-function-elimination -fblas-matmul-limit=@var{n} @gol
|
|
|
745403 |
--fbounds-check -fcheck-array-temporaries @gol
|
|
|
745403 |
+-fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol
|
|
|
745403 |
+-fcheck-array-temporaries @gol
|
|
|
745403 |
-fcheck=@var{<all|array-temps|bounds|do|mem|pointer|recursion>} @gol
|
|
|
745403 |
-fcoarray=@var{<none|single|lib>} -fexternal-blas -ff2c
|
|
|
745403 |
-ffrontend-loop-interchange @gol
|
|
|
745403 |
@@ -1580,6 +1581,39 @@ warnings for generated array temporaries.
|
|
|
745403 |
@c Note: This option is also referred in gcc's manpage
|
|
|
745403 |
Deprecated alias for @option{-fcheck=bounds}.
|
|
|
745403 |
|
|
|
745403 |
+@item -ftail-call-workaround
|
|
|
745403 |
+@itemx -ftail-call-workaround=@var{n}
|
|
|
745403 |
+@opindex @code{tail-call-workaround}
|
|
|
745403 |
+Some C interfaces to Fortran codes violate the gfortran ABI by
|
|
|
745403 |
+omitting the hidden character length arguments as described in
|
|
|
745403 |
+@xref{Argument passing conventions}. This can lead to crashes
|
|
|
745403 |
+because pushing arguments for tail calls can overflow the stack.
|
|
|
745403 |
+
|
|
|
745403 |
+To provide a workaround for existing binary packages, this option
|
|
|
745403 |
+disables tail call optimization for gfortran procedures with character
|
|
|
745403 |
+arguments. With @option{-ftail-call-workaround=2} tail call optimization
|
|
|
745403 |
+is disabled in all gfortran procedures with character arguments,
|
|
|
745403 |
+with @option{-ftail-call-workaround=1} or equivalent
|
|
|
745403 |
+@option{-ftail-call-workaround} only in gfortran procedures with character
|
|
|
745403 |
+arguments that call implicitly prototyped procedures.
|
|
|
745403 |
+
|
|
|
745403 |
+Using this option can lead to problems including crashes due to
|
|
|
745403 |
+insufficient stack space.
|
|
|
745403 |
+
|
|
|
745403 |
+It is @emph{very strongly} recommended to fix the code in question.
|
|
|
745403 |
+The @option{-fc-prototypes-external} option can be used to generate
|
|
|
745403 |
+prototypes which conform to gfortran's ABI, for inclusion in the
|
|
|
745403 |
+source code.
|
|
|
745403 |
+
|
|
|
745403 |
+Support for this option will likely be withdrawn in a future release
|
|
|
745403 |
+of gfortran.
|
|
|
745403 |
+
|
|
|
745403 |
+The negative form, @option{-fno-tail-call-workaround} or equivalent
|
|
|
745403 |
+@option{-ftail-call-workaround=0}, can be used to disable this option.
|
|
|
745403 |
+
|
|
|
745403 |
+Default is currently @option{-ftail-call-workaround}, this will change
|
|
|
745403 |
+in future releases.
|
|
|
745403 |
+
|
|
|
745403 |
@item -fcheck-array-temporaries
|
|
|
745403 |
@opindex @code{fcheck-array-temporaries}
|
|
|
745403 |
Deprecated alias for @option{-fcheck=array-temps}.
|
|
|
745403 |
--- gcc/fortran/lang.opt
|
|
|
745403 |
+++ gcc/fortran/lang.opt
|
|
|
745403 |
@@ -742,6 +742,13 @@ fsign-zero
|
|
|
745403 |
Fortran Var(flag_sign_zero) Init(1)
|
|
|
745403 |
Apply negative sign to zero values.
|
|
|
745403 |
|
|
|
745403 |
+ftail-call-workaround
|
|
|
745403 |
+Fortran Alias(ftail-call-workaround=,1,0)
|
|
|
745403 |
+
|
|
|
745403 |
+ftail-call-workaround=
|
|
|
745403 |
+Fortran RejectNegative Joined UInteger IntegerRange(0, 2) Var(flag_tail_call_workaround) Init(1)
|
|
|
745403 |
+Disallow tail call optimization when a calling routine may have omitted character lengths.
|
|
|
745403 |
+
|
|
|
745403 |
funderscoring
|
|
|
745403 |
Fortran Var(flag_underscoring) Init(1)
|
|
|
745403 |
Append underscores to externally visible names.
|
|
|
745403 |
--- gcc/fortran/trans-decl.c
|
|
|
745403 |
+++ gcc/fortran/trans-decl.c
|
|
|
745403 |
@@ -2513,6 +2513,17 @@ create_function_arglist (gfc_symbol * sym)
|
|
|
745403 |
TREE_READONLY (length) = 1;
|
|
|
745403 |
gfc_finish_decl (length);
|
|
|
745403 |
|
|
|
745403 |
+ /* Marking the length DECL_HIDDEN_STRING_LENGTH will lead
|
|
|
745403 |
+ to tail calls being disabled. Only do that if we
|
|
|
745403 |
+ potentially have broken callers. */
|
|
|
745403 |
+ if (flag_tail_call_workaround
|
|
|
745403 |
+ && f->sym->ts.u.cl
|
|
|
745403 |
+ && f->sym->ts.u.cl->length
|
|
|
745403 |
+ && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
|
|
|
745403 |
+ && (flag_tail_call_workaround == 2
|
|
|
745403 |
+ || f->sym->ns->implicit_interface_calls))
|
|
|
745403 |
+ DECL_HIDDEN_STRING_LENGTH (length) = 1;
|
|
|
745403 |
+
|
|
|
745403 |
/* Remember the passed value. */
|
|
|
745403 |
if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length)
|
|
|
745403 |
{
|
|
|
745403 |
--- gcc/lto-streamer.h
|
|
|
745403 |
+++ gcc/lto-streamer.h
|
|
|
745403 |
@@ -121,7 +121,7 @@ along with GCC; see the file COPYING3. If not see
|
|
|
745403 |
form followed by the data for the string. */
|
|
|
745403 |
|
|
|
745403 |
#define LTO_major_version 7
|
|
|
745403 |
-#define LTO_minor_version 1
|
|
|
745403 |
+#define LTO_minor_version 2
|
|
|
745403 |
|
|
|
745403 |
typedef unsigned char lto_decl_flags_t;
|
|
|
745403 |
|
|
|
745403 |
--- gcc/tree-core.h
|
|
|
745403 |
+++ gcc/tree-core.h
|
|
|
745403 |
@@ -1644,6 +1644,7 @@ struct GTY(()) tree_decl_common {
|
|
|
745403 |
/* In a VAR_DECL and PARM_DECL, this is DECL_READ_P. */
|
|
|
745403 |
unsigned decl_read_flag : 1;
|
|
|
745403 |
/* In a VAR_DECL or RESULT_DECL, this is DECL_NONSHAREABLE. */
|
|
|
745403 |
+ /* In a PARM_DECL, this is DECL_HIDDEN_STRING_LENGTH. */
|
|
|
745403 |
unsigned decl_nonshareable_flag : 1;
|
|
|
745403 |
|
|
|
745403 |
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
|
|
|
745403 |
--- gcc/tree-streamer-in.c
|
|
|
745403 |
+++ gcc/tree-streamer-in.c
|
|
|
745403 |
@@ -252,7 +252,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
|
|
|
745403 |
LABEL_DECL_UID (expr) = -1;
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
- if (TREE_CODE (expr) == FIELD_DECL)
|
|
|
745403 |
+ else if (TREE_CODE (expr) == FIELD_DECL)
|
|
|
745403 |
{
|
|
|
745403 |
DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
|
|
|
745403 |
DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
|
|
|
745403 |
@@ -260,12 +260,15 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
|
|
|
745403 |
expr->decl_common.off_align = bp_unpack_value (bp, 8);
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
- if (VAR_P (expr))
|
|
|
745403 |
+ else if (VAR_P (expr))
|
|
|
745403 |
{
|
|
|
745403 |
DECL_HAS_DEBUG_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
|
|
|
745403 |
DECL_NONLOCAL_FRAME (expr) = (unsigned) bp_unpack_value (bp, 1);
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
+ else if (TREE_CODE (expr) == PARM_DECL)
|
|
|
745403 |
+ DECL_HIDDEN_STRING_LENGTH (expr) = (unsigned) bp_unpack_value (bp, 1);
|
|
|
745403 |
+
|
|
|
745403 |
if (TREE_CODE (expr) == RESULT_DECL
|
|
|
745403 |
|| TREE_CODE (expr) == PARM_DECL
|
|
|
745403 |
|| VAR_P (expr))
|
|
|
745403 |
--- gcc/tree-streamer-out.c
|
|
|
745403 |
+++ gcc/tree-streamer-out.c
|
|
|
745403 |
@@ -212,7 +212,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
|
|
|
745403 |
bp_pack_var_len_unsigned (bp, EH_LANDING_PAD_NR (expr));
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
- if (TREE_CODE (expr) == FIELD_DECL)
|
|
|
745403 |
+ else if (TREE_CODE (expr) == FIELD_DECL)
|
|
|
745403 |
{
|
|
|
745403 |
bp_pack_value (bp, DECL_PACKED (expr), 1);
|
|
|
745403 |
bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
|
|
|
745403 |
@@ -220,12 +220,15 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
|
|
|
745403 |
bp_pack_value (bp, expr->decl_common.off_align, 8);
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
- if (VAR_P (expr))
|
|
|
745403 |
+ else if (VAR_P (expr))
|
|
|
745403 |
{
|
|
|
745403 |
bp_pack_value (bp, DECL_HAS_DEBUG_EXPR_P (expr), 1);
|
|
|
745403 |
bp_pack_value (bp, DECL_NONLOCAL_FRAME (expr), 1);
|
|
|
745403 |
}
|
|
|
745403 |
|
|
|
745403 |
+ else if (TREE_CODE (expr) == PARM_DECL)
|
|
|
745403 |
+ bp_pack_value (bp, DECL_HIDDEN_STRING_LENGTH (expr), 1);
|
|
|
745403 |
+
|
|
|
745403 |
if (TREE_CODE (expr) == RESULT_DECL
|
|
|
745403 |
|| TREE_CODE (expr) == PARM_DECL
|
|
|
745403 |
|| VAR_P (expr))
|
|
|
745403 |
--- gcc/tree.h
|
|
|
745403 |
+++ gcc/tree.h
|
|
|
745403 |
@@ -909,6 +909,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
|
|
|
745403 |
(TREE_CHECK2 (NODE, VAR_DECL, \
|
|
|
745403 |
RESULT_DECL)->decl_common.decl_nonshareable_flag)
|
|
|
745403 |
|
|
|
745403 |
+/* In a PARM_DECL, set for Fortran hidden string length arguments that some
|
|
|
745403 |
+ buggy callers don't pass to the callee. */
|
|
|
745403 |
+#define DECL_HIDDEN_STRING_LENGTH(NODE) \
|
|
|
745403 |
+ (TREE_CHECK (NODE, PARM_DECL)->decl_common.decl_nonshareable_flag)
|
|
|
745403 |
+
|
|
|
745403 |
/* In a CALL_EXPR, means that the call is the jump from a thunk to the
|
|
|
745403 |
thunked-to function. */
|
|
|
745403 |
#define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag)
|