Skip to content

Commit

Permalink
PR tree-optimization/78512 - [7 Regression] r242674 miscompiles Linux…
Browse files Browse the repository at this point in the history
… kernel

gcc/ChangeLog:

	PR tree-optimization/78512
	* config/linux.h (TARGET_PRINTF_POINTER_FORMAT): Remove.
	* config/rs6000/linux.h: Same.
	* config/rs6000/linux64.h: Same.
	* config/sol2.h: Same.
	* config/sol2.c (solaris_printf_pointer_format): Remove.
	* doc/tm.texi.in (TARGET_PRINTF_POINTER_FORMAT): Remove.
	* doc/tm.texi: Regenerate.
	* gimple-ssa-sprintf.c (format_pointer): Rempove.
	(pass_sprintf_length::compute_format_length): Return bool.
	(pass_sprintf_length::handle_gimple_call): Adjust.
	* target.def (printf_pointer_format): Remove.
	* targhooks.c (default_printf_pointer_format): Remove.
	(linux_printf_pointer_format): Same.
	* targhooks.h (default_printf_pointer_format): Remove.
	(linux_printf_pointer_format, solaris_printf_pointer_format): Same.

gcc/testsuite/ChangeLog:

	PR tree-optimization/78512
	* gcc.dg/tree-ssa/builtin-sprintf-6.c: Add test cases.
	* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Remove test cases.



git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242975 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
msebor committed Nov 29, 2016
1 parent 3be67a6 commit 72d5639
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 193 deletions.
19 changes: 19 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
2016-11-29 Martin Sebor <msebor@redhat.com>

PR tree-optimization/78512
* config/linux.h (TARGET_PRINTF_POINTER_FORMAT): Remove.
* config/rs6000/linux.h: Same.
* config/rs6000/linux64.h: Same.
* config/sol2.h: Same.
* config/sol2.c (solaris_printf_pointer_format): Remove.
* doc/tm.texi.in (TARGET_PRINTF_POINTER_FORMAT): Remove.
* doc/tm.texi: Regenerate.
* gimple-ssa-sprintf.c (format_pointer): Rempove.
(pass_sprintf_length::compute_format_length): Return bool.
(pass_sprintf_length::handle_gimple_call): Adjust.
* target.def (printf_pointer_format): Remove.
* targhooks.c (default_printf_pointer_format): Remove.
(linux_printf_pointer_format): Same.
* targhooks.h (default_printf_pointer_format): Remove.
(linux_printf_pointer_format, solaris_printf_pointer_format): Same.

2016-11-29 Uros Bizjak <ubizjak@gmail.com>

* config/i386/sse.md (UNSPEC_MASKOP): Move from i386.md.
Expand Down
5 changes: 0 additions & 5 deletions gcc/config/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,3 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# define TARGET_LIBC_HAS_FUNCTION linux_libc_has_function

#endif

/* The format string to which "%p" corresponds (same in Glibc and
uClibc. */
#undef TARGET_PRINTF_POINTER_FORMAT
#define TARGET_PRINTF_POINTER_FORMAT linux_printf_pointer_format
4 changes: 0 additions & 4 deletions gcc/config/rs6000/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,3 @@
|| (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 19)
#define RS6000_GLIBC_ATOMIC_FENV 1
#endif

/* The format string to which "%p" corresponds. */
#undef TARGET_PRINTF_POINTER_FORMAT
#define TARGET_PRINTF_POINTER_FORMAT linux_printf_pointer_format
4 changes: 0 additions & 4 deletions gcc/config/rs6000/linux64.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,3 @@ extern int dot_symbols;
enabling the __float128 keyword. */
#undef TARGET_FLOAT128_ENABLE_TYPE
#define TARGET_FLOAT128_ENABLE_TYPE 1

/* The format string to which "%p" corresponds. */
#undef TARGET_PRINTF_POINTER_FORMAT
#define TARGET_PRINTF_POINTER_FORMAT linux_printf_pointer_format
14 changes: 0 additions & 14 deletions gcc/config/sol2.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ along with GCC; see the file COPYING3. If not see
#include "varasm.h"
#include "output.h"

#undef TARGET_PRINTF_POINTER_FORMAT
#define TARGET_PRINTF_POINTER_FORMAT solaris_printf_pointer_format

tree solaris_pending_aligns, solaris_pending_inits, solaris_pending_finis;

/* Attach any pending attributes for DECL to the list in *ATTRIBUTES.
Expand Down Expand Up @@ -301,14 +298,3 @@ solaris_override_options (void)
if (!HAVE_LD_EH_FRAME_CIEV3 && !global_options_set.x_dwarf_version)
dwarf_version = 2;
}

/* Solaris libc formats pointers as if by "%zx" with the pound ('#')
format flag having the same meaning as in the integer directive. */

const char*
solaris_printf_pointer_format (tree, const char **flags)
{
*flags = "#";

return "%zx";
}
4 changes: 0 additions & 4 deletions gcc/config/sol2.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,10 +440,6 @@ along with GCC; see the file COPYING3. If not see
#undef TARGET_LIBC_HAS_FUNCTION
#define TARGET_LIBC_HAS_FUNCTION default_libc_has_function

/* The format string to which "%p" corresponds. */
#undef TARGET_LIBC_PRINTF_POINTER_FORMAT
#define TARGET_LIBC_PRINTF_POINTER_FORMAT solaris_libc_printf_pointer_format

extern GTY(()) tree solaris_pending_aligns;
extern GTY(()) tree solaris_pending_inits;
extern GTY(()) tree solaris_pending_finis;
4 changes: 0 additions & 4 deletions gcc/doc/tm.texi
Original file line number Diff line number Diff line change
Expand Up @@ -5422,10 +5422,6 @@ In either case, it remains possible to select code-generation for the alternate
scheme, by means of compiler command line switches.
@end defmac

@deftypefn {Target Hook} {const char*} TARGET_PRINTF_POINTER_FORMAT (tree, const char **@var{flags})
Determine the target @code{printf} implementation format string that the most closely corresponds to the @code{%p} format directive. The object pointed to by the @var{flags} is set to a string consisting of recognized format flags such as the @code{'#'} character.
@end deftypefn

@node Addressing Modes
@section Addressing Modes
@cindex addressing modes
Expand Down
2 changes: 0 additions & 2 deletions gcc/doc/tm.texi.in
Original file line number Diff line number Diff line change
Expand Up @@ -4106,8 +4106,6 @@ In either case, it remains possible to select code-generation for the alternate
scheme, by means of compiler command line switches.
@end defmac

@hook TARGET_PRINTF_POINTER_FORMAT

@node Addressing Modes
@section Addressing Modes
@cindex addressing modes
Expand Down
119 changes: 29 additions & 90 deletions gcc/gimple-ssa-sprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ along with GCC; see the file COPYING3. If not see

#include "realmpfr.h"
#include "target.h"
#include "targhooks.h"

#include "cpplib.h"
#include "input.h"
Expand Down Expand Up @@ -126,7 +125,7 @@ class pass_sprintf_length : public gimple_opt_pass
void handle_gimple_call (gimple_stmt_iterator*);

struct call_info;
void compute_format_length (const call_info &, format_result *);
bool compute_format_length (const call_info &, format_result *);
};

bool
Expand Down Expand Up @@ -759,83 +758,12 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
}
}

static fmtresult
format_integer (const conversion_spec &, tree);

/* Return a range representing the minimum and maximum number of bytes
that the conversion specification SPEC will write on output for the
pointer argument ARG when non-null. ARG may be null (for vararg
functions). */

static fmtresult
format_pointer (const conversion_spec &spec, tree arg)
{
fmtresult res;

/* Determine the target's integer format corresponding to "%p". */
const char *flags;
const char *pfmt = targetm.printf_pointer_format (arg, &flags);
if (!pfmt)
{
/* The format couldn't be determined. */
res.range.min = res.range.max = HOST_WIDE_INT_M1U;
return res;
}

if (pfmt [0] == '%')
{
/* Format the pointer using the integer format string. */
conversion_spec pspec = spec;

/* Clear flags that are not listed as recognized. */
for (const char *pf = "+ #0"; *pf; ++pf)
{
if (!strchr (flags, *pf))
pspec.clear_flag (*pf);
}

/* Set flags that are specified in the format string. */
bool flag_p = true;
do
{
switch (*++pfmt)
{
case '+': case ' ': case '#': case '0':
pspec.set_flag (*pfmt);
break;
default:
flag_p = false;
}
}
while (flag_p);

/* Set the appropriate length modifier taking care to clear
the one that may be set (Glibc's %p accepts but ignores all
the integer length modifiers). */
switch (*pfmt)
{
case 'l': pspec.modifier = FMT_LEN_l; ++pfmt; break;
case 't': pspec.modifier = FMT_LEN_t; ++pfmt; break;
case 'z': pspec.modifier = FMT_LEN_z; ++pfmt; break;
default: pspec.modifier = FMT_LEN_none;
}

pspec.force_flags = 1;
pspec.specifier = *pfmt++;
gcc_assert (*pfmt == '\0');
return format_integer (pspec, arg);
}

/* The format is a plain string such as Glibc's "(nil)". */
res.range.min = res.range.max = strlen (pfmt);
return res;
}

/* Set *PWIDTH and *PPREC according to the width and precision specified
in SPEC. Each is set to HOST_WIDE_INT_MIN when the corresponding
field is specified but unknown, to zero for width and -1 for precision,
respectively when it's not specified, or to a non-negative value
corresponding to the known value. */

static void
get_width_and_precision (const conversion_spec &spec,
HOST_WIDE_INT *pwidth, HOST_WIDE_INT *pprec)
Expand Down Expand Up @@ -867,7 +795,6 @@ get_width_and_precision (const conversion_spec &spec,
*pprec = prec;
}


/* Return a range representing the minimum and maximum number of bytes
that the conversion specification SPEC will write on output for the
integer argument ARG when non-null. ARG may be null (for vararg
Expand Down Expand Up @@ -2257,9 +2184,12 @@ add_bytes (const pass_sprintf_length::call_info &info,

/* Compute the length of the output resulting from the call to a formatted
output function described by INFO and store the result of the call in
*RES. Issue warnings for detected past the end writes. */
*RES. Issue warnings for detected past the end writes. Return true
if the complete format string has been processed and *RES can be relied
on, false otherwise (e.g., when a unknown or unhandled directive was seen
that caused the processing to be terminated early). */

void
bool
pass_sprintf_length::compute_format_length (const call_info &info,
format_result *res)
{
Expand Down Expand Up @@ -2299,7 +2229,7 @@ pass_sprintf_length::compute_format_length (const call_info &info,
if (0 && *pf == 0)
{
/* Incomplete directive. */
return;
return false;
}

conversion_spec spec = conversion_spec ();
Expand All @@ -2322,10 +2252,10 @@ pass_sprintf_length::compute_format_length (const call_info &info,
{
/* Similarly to the block above, this could be either a POSIX
positional argument or a width, depending on what follows. */
if (argno < gimple_call_num_args (info.callstmt))
spec.star_width = gimple_call_arg (info.callstmt, argno++);
else
return;
if (gimple_call_num_args (info.callstmt) <= argno)
return false;

spec.star_width = gimple_call_arg (info.callstmt, argno++);
++pf;
}

Expand All @@ -2344,7 +2274,7 @@ pass_sprintf_length::compute_format_length (const call_info &info,
if (dollar == 0
|| dollar == info.argidx
|| dollar > gimple_call_num_args (info.callstmt))
return;
return false;

--dollar;

Expand Down Expand Up @@ -2411,7 +2341,7 @@ pass_sprintf_length::compute_format_length (const call_info &info,
estimate the upper bound on the size of the output
based on the number of digits it probably isn't worth
continuing. */
return;
return false;
}
}

Expand Down Expand Up @@ -2520,11 +2450,14 @@ pass_sprintf_length::compute_format_length (const call_info &info,
break;

case 'p':
spec.fmtfunc = format_pointer;
break;
/* The %p output is implementation-defined. It's possible
to determine this format but due to extensions (especially
those of the Linux kernel -- see bug 78512) the first %p
in the format string disables any further processing. */
return false;

case 'n':
return;
break;

case 'c':
case 'S':
Expand All @@ -2533,7 +2466,8 @@ pass_sprintf_length::compute_format_length (const call_info &info,
break;

default:
return;
/* Unknown conversion specification. */
return false;
}

spec.specifier = *pf++;
Expand All @@ -2552,6 +2486,9 @@ pass_sprintf_length::compute_format_length (const call_info &info,

::format_directive (info, res, dir, dirlen, spec, arg);
}

/* Complete format string was processed (with or without warnings). */
return true;
}

/* Return the size of the object referenced by the expression DEST if
Expand Down Expand Up @@ -2893,13 +2830,15 @@ pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi)
/* The result is the number of bytes output by the formatted function,
including the terminating NUL. */
format_result res = format_result ();
compute_format_length (info, &res);

bool success = compute_format_length (info, &res);

/* When optimizing and the printf return value optimization is enabled,
attempt to substitute the computed result for the return value of
the call. Avoid this optimization when -frounding-math is in effect
and the format string contains a floating point directive. */
if (optimize > 0
if (success
&& optimize > 0
&& flag_printf_return_value
&& (!flag_rounding_math || !res.floating))
try_substitute_return_value (gsi, info, res);
Expand Down
6 changes: 0 additions & 6 deletions gcc/target.def
Original file line number Diff line number Diff line change
Expand Up @@ -3381,12 +3381,6 @@ greater than 128 and a multiple of 32.",
machine_mode, (int n, bool extended),
default_floatn_mode)

DEFHOOK
(printf_pointer_format,
"Determine the target @code{printf} implementation format string that the most closely corresponds to the @code{%p} format directive. The object pointed to by the @var{flags} is set to a string consisting of recognized format flags such as the @code{'#'} character.",
const char*, (tree, const char **flags),
default_printf_pointer_format)

/* Compute cost of moving data from a register of class FROM to one of
TO, using MODE. */
DEFHOOK
Expand Down
30 changes: 0 additions & 30 deletions gcc/targhooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -1512,36 +1512,6 @@ no_c99_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
return false;
}

/* Return the format string to which "%p" corresponds. By default,
assume it corresponds to the C99 "%zx" format and set *FLAGS to
the empty string to indicate that format flags have no effect.
An example of an implementation that matches this description
is AIX. */

const char*
default_printf_pointer_format (tree, const char **flags)
{
*flags = "";

return "%zx";
}

/* For Glibc and uClibc targets also define the hook here because
otherwise it would have to be duplicated in each target's .c file
(such as in bfin/bfin.c and c6x/c6x.c, etc.)
Glibc and uClibc format pointers as if by "%zx" except for the null
pointer which outputs "(nil)". It ignores the pound ('#') format
flag but interprets the space and plus flags the same as in the integer
directive. */

const char*
linux_printf_pointer_format (tree arg, const char **flags)
{
*flags = " +";

return arg && integer_zerop (arg) ? "(nil)" : "%#zx";
}

tree
default_builtin_tm_load_store (tree ARG_UNUSED (type))
{
Expand Down
4 changes: 0 additions & 4 deletions gcc/targhooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,6 @@ extern bool default_libc_has_function (enum function_class);
extern bool no_c99_libc_has_function (enum function_class);
extern bool gnu_libc_has_function (enum function_class);

extern const char* default_printf_pointer_format (tree, const char **);
extern const char* linux_printf_pointer_format (tree, const char **);
extern const char* solaris_printf_pointer_format (tree, const char **);

extern tree default_builtin_tm_load_store (tree);

extern int default_memory_move_cost (machine_mode, reg_class_t, bool);
Expand Down
6 changes: 6 additions & 0 deletions gcc/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
2016-11-29 Martin Sebor <msebor@redhat.com>

PR tree-optimization/78512
* gcc.dg/tree-ssa/builtin-sprintf-6.c: Add test cases.
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Remove test cases.

2016-11-29 Uros Bizjak <ubizjak@gmail.com>

* gcc.target/i386/avx512f-kmovw-1.c (avx512f_test):
Expand Down
Loading

0 comments on commit 72d5639

Please sign in to comment.