diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 35bd9e2f2322d..5fa6e032be463 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,12 @@ +2017-08-02 Yury Gribov + + * mklog: Added new implementation. + +2017-08-02 Yury Gribov + + * mklog: Rename to ... + * mklog.pl: this. + 2017-07-17 Yury Gribov * mklog: Fix extraction of changed file name. diff --git a/contrib/mklog b/contrib/mklog index ff20cf1ba0f74..0622d2e2e3db9 100755 --- a/contrib/mklog +++ b/contrib/mklog @@ -1,5 +1,6 @@ -#!/usr/bin/perl -# Copyright (C) 2012-2017 Free Software Foundation, Inc. +#!/usr/bin/python + +# Copyright (C) 2017 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -20,343 +21,450 @@ # This script parses a .diff file generated with 'diff -up' or 'diff -cp' # and adds a skeleton ChangeLog file to the file. It does not try to be -# very smart when parsing function names, but it produces a reasonable +# too smart when parsing function names, but it produces a reasonable # approximation. # -# Author: Diego Novillo and -# Cary Coutant - -use File::Temp; -use File::Copy qw(cp mv); - -$date = `date +%Y-%m-%d`; chop ($date); - -$dot_mklog_format_msg = - "The .mklog format is:\n" - . "NAME = ...\n" - . "EMAIL = ...\n"; - -# Create a .mklog to reflect your profile, if necessary. -my $conf = "$ENV{HOME}/.mklog"; -if (-f "$conf") { - open (CONF, "$conf") - or die "Could not open file '$conf' for reading: $!\n"; - while () { - if (m/^\s*NAME\s*=\s*(.*?)\s*$/) { - $name = $1; - } elsif (m/^\s*EMAIL\s*=\s*(.*?)\s*$/) { - $addr = $1; - } - } - if (!($name && $addr)) { - die "Could not read .mklog settings.\n" - . $dot_mklog_format_msg; - } -} else { - $name = `git config user.name`; - chomp($name); - $addr = `git config user.email`; - chomp($addr); - - if (!($name && $addr)) { - die "Could not read git user.name and user.email settings.\n" - . "Please add missing git settings, or create a .mklog file in" - . " $ENV{HOME}.\n" - . $dot_mklog_format_msg; - } -} - -$gcc_root = $0; -$gcc_root =~ s/[^\\\/]+$/../; - -#----------------------------------------------------------------------------- -# Program starts here. You should not need to edit anything below this -# line. -#----------------------------------------------------------------------------- -$inline = 0; -if ($#ARGV == 1 && ("$ARGV[0]" eq "-i" || "$ARGV[0]" eq "--inline")) { - shift; - $inline = 1; -} elsif ($#ARGV != 0) { - $prog = `basename $0`; chop ($prog); - print <); -close (DFILE); - -# Array diff_lines is modified by the log generation, so save a copy in -# orig_diff_lines if needed. -if ($inline) { - @orig_diff_lines = @diff_lines; -} - -# For every file in the .diff print all the function names in ChangeLog -# format. -%cl_entries = (); -$change_msg = undef; -$look_for_funs = 0; -$clname = get_clname(''); -$line_idx = 0; -foreach (@diff_lines) { - # Stop processing functions if we found a new file. - # Remember both left and right names because one may be /dev/null. - # Don't be fooled by line markers in case of context diff. - if (!/\*\*\*$/ && /^[+*][+*][+*] +(\S+)/) { - $left = remove_suffixes ($1); - $look_for_funs = 0; - } - if (!/---$/ && /^--- +(\S+)?/) { - $right = remove_suffixes ($1); - $look_for_funs = 0; - } - - # Check if the body of diff started. - # We should now have both left and right name, - # so we can decide filename. - - if ($left && (/^\*{15}/ || /^@@ /)) { - # If we have not seen any function names in the previous file (ie, - # $change_msg is empty), we just write out a ':' before starting the next - # file. - if ($clname) { - $cl_entries{$clname} .= $change_msg ? "$change_msg" : ":\n"; - } - - if ($left eq $right) { - $filename = $left; - } elsif($left eq '/dev/null') { - $filename = $right; - } elsif($right eq '/dev/null') { - $filename = $left; - } else { - my @ldirs = split /[\/\\]/, $left; - my @rdirs = split /[\/\\]/, $right; - - $filename = ''; - while ((my $l = pop @ldirs) && (my $r = pop @rdirs)) { - last if ($l ne $r); - $filename = "$l/$filename"; - } - $filename =~ s/\/$//; - - if (!$filename) { - print STDERR "Error: failed to parse diff for $left and $right\n"; - exit 1; - } - } - $left = $right = undef; - ($clname, $relname) = get_clname ($filename); - $cl_entries{$clname} .= "\t* $relname"; - $change_msg = ''; - $look_for_funs = $filename =~ '\.(c|cpp|C|cc|h|inc|def)$'; - } - +# This is a straightforward adaptation of original Perl script. +# +# Author: Yury Gribov + +import sys +import re +import os.path +import os +import getopt +import tempfile +import time +import shutil +from subprocess import Popen, PIPE + +me = os.path.basename(sys.argv[0]) + +def error(msg): + sys.stderr.write("%s: error: %s\n" % (me, msg)) + sys.exit(1) + +def warn(msg): + sys.stderr.write("%s: warning: %s\n" % (me, msg)) + +class RegexCache(object): + """Simple trick to Perl-like combined match-and-bind.""" + + def __init__(self): + self.last_match = None + + def match(self, p, s): + self.last_match = re.match(p, s) if isinstance(p, str) else p.match(s) + return self.last_match + + def search(self, p, s): + self.last_match = re.search(p, s) if isinstance(p, str) else p.search(s) + return self.last_match + + def group(self, n): + return self.last_match.group(n) + +cache = RegexCache() + +def print_help_and_exit(): + print """\ +Usage: %s [-i | --inline] [PATCH] +Generate ChangeLog template for PATCH. +PATCH must be generated using diff(1)'s -up or -cp options +(or their equivalent in Subversion/git). + +When PATCH is - or missing, read standard input. + +When -i is used, prepends ChangeLog to PATCH. +If PATCH is not stdin, modifies PATCH in-place, otherwise writes +to stdout. +""" % me + sys.exit(1) + +def run(cmd, die_on_error): + """Simple wrapper for Popen.""" + proc = Popen(cmd.split(' '), stderr = PIPE, stdout = PIPE) + (out, err) = proc.communicate() + if die_on_error and proc.returncode != 0: + error("`%s` failed:\n" % (cmd, proc.stderr)) + return proc.returncode, out, err + +def read_user_info(): + dot_mklog_format_msg = """\ +The .mklog format is: +NAME = ... +EMAIL = ... +""" + + # First try to read .mklog config + mklog_conf = os.path.expanduser('~/.mklog') + if os.path.exists(mklog_conf): + attrs = {} + f = open(mklog_conf, 'rb') + for s in f: + if cache.match(r'^\s*([a-zA-Z0-9_]+)\s*=\s*(.*?)\s*$', s): + attrs[cache.group(1)] = cache.group(2) + f.close() + if 'NAME' not in attrs: + error("'NAME' not present in .mklog") + if 'EMAIL' not in attrs: + error("'EMAIL' not present in .mklog") + return attrs['NAME'], attrs['EMAIL'] + + # Otherwise go with git + + rc1, name, _ = run('git config user.name', False) + name = name.rstrip() + rc2, email, _ = run('git config user.email', False) + email = email.rstrip() + + if rc1 != 0 or rc2 != 0: + error("""\ +Could not read git user.name and user.email settings. +Please add missing git settings, or create a %s. +""" % mklog_conf) + + return name, email + +def get_parent_changelog (s): + """See which ChangeLog this file change should go to.""" + + if s.find('\\') == -1 and s.find('/') == -1: + return "ChangeLog", s + + gcc_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + + d = s + while d: + clname = d + "/ChangeLog" + if os.path.exists(gcc_root + '/' + clname) or os.path.exists(clname): + relname = s[len(d)+1:] + return clname, relname + d, _ = os.path.split(d) + + return "Unknown ChangeLog", s + +class FileDiff: + """Class to represent changes in a single file.""" + + def __init__(self, filename): + self.filename = filename + self.hunks = [] + self.clname, self.relname = get_parent_changelog(filename); + + def dump(self): + print "Diff for %s:\n ChangeLog = %s\n rel name = %s\n" % (self.filename, self.clname, self.relname) + for i, h in enumerate(self.hunks): + print "Next hunk %d:" % i + h.dump() + +class Hunk: + """Class to represent a single hunk of changes.""" + + def __init__(self, hdr): + self.hdr = hdr + self.lines = [] + self.ctx_diff = is_ctx_hunk_start(hdr) + + def dump(self): + print '%s' % self.hdr + print '%s' % '\n'.join(self.lines) + + def is_file_addition(self): + """Does hunk describe addition of file?""" + if self.ctx_diff: + for line in self.lines: + if re.match(r'^\*\*\* 0 \*\*\*\*', line): + return True + else: + return re.match(r'^@@ -0,0 \+1.* @@', self.hdr) + + def is_file_removal(self): + """Does hunk describe removal of file?""" + if self.ctx_diff: + for line in self.lines: + if re.match(r'^--- 0 ----', line): + return True + else: + return re.match(r'^@@ -1.* \+0,0 @@', self.hdr) + +def is_file_diff_start(s): + # Don't be fooled by context diff line markers: + # *** 385,391 **** + return ((s.startswith('***') and not s.endswith('***')) + or (s.startswith('---') and not s.endswith('---'))) + +def is_ctx_hunk_start(s): + return re.match(r'^\*\*\*\*\*\**', s) + +def is_uni_hunk_start(s): + return re.match(r'^@@ .* @@', s) + +def is_hunk_start(s): + return is_ctx_hunk_start(s) or is_uni_hunk_start(s) + +def remove_suffixes(s): + if s.startswith('a/') or s.startswith('b/'): + s = s[2:] + if s.endswith('.jj'): + s = s[:-3] + return s + +def find_changed_funs(hunk): + """Find all functions touched by hunk. We don't try too hard + to find good matches. This should return a superset + of the actual set of functions in the .diff file. + """ + + fns = [] + fn = None + + if (cache.match(r'^\*\*\*\*\*\** ([a-zA-Z0-9_].*)', hunk.hdr) + or cache.match(r'^@@ .* @@ ([a-zA-Z0-9_].*)', hunk.hdr)): + fn = cache.group(1) + + for i, line in enumerate(hunk.lines): # Context diffs have extra whitespace after first char; # remove it to make matching easier. - if ($is_context_diff) { - s/^([-+! ]) /\1/; - } - - # Remember the last line in a diff block that might start - # a new function. - if (/^[-+! ]([a-zA-Z0-9_].*)/) { - $save_fn = $1; - } - - # Check if file is newly added. - # Two patterns: for context and unified diff. - if (/^\*\*\* 0 \*\*\*\*/ - || /^@@ -0,0 \+1.* @@/) { - $change_msg = $filename =~ /testsuite.*(?]*>//); - $fn =~ s/[ \t]*$//; - } - # Check is function really modified - $no_real_change = 0; - $idx = $line_idx; - # Skip line info in context diffs. - while ($idx <= $#diff_lines && $is_context_diff - && $diff_lines[$idx + 1] =~ /^[-\*]{3} [0-9]/) { - ++$idx; - } - # Check all lines till the first change - # for the presence of really changed function - do { - ++$idx; - $no_real_change = $idx > $#diff_lines - || is_top_level ($diff_lines[$idx], $is_context_diff); - } while (!$no_real_change && ($diff_lines[$idx] !~ /^[-+!]/)); - if ($fn && !$seen_names{$fn} && !$no_real_change) { - # If this is the first function in the file, we display it next - # to the filename, so we need an extra space before the opening - # brace. - if (!$change_msg) { - $change_msg .= " "; - } else { - $change_msg .= "\t"; - } - - $change_msg .= "($fn):\n"; - $seen_names{$fn} = 1; - } - } - $line_idx++; -} - -# If we have not seen any function names (ie, $change_msg is empty), we just -# write out a ':'. This happens when there is only one file with no -# functions. -$cl_entries{$clname} .= $change_msg ? "$change_msg\n" : ":\n"; - -if ($inline && $diff ne "-") { - # Get a temp filename, rather than an open filehandle, because we use - # the open to truncate. - $tmp = mktemp("tmp.XXXXXXXX") or die "Could not create temp file: $!"; - - # Copy the permissions to the temp file (in File::Copy module version - # 2.15 and later). - cp $diff, $tmp or die "Could not copy patch file to temp file: $!"; - - # Open the temp file, clearing contents. - open (OUTPUTFILE, '>', $tmp) or die "Could not open temp file: $!"; -} else { - *OUTPUTFILE = STDOUT; -} - -# Print the log -foreach my $clname (keys %cl_entries) { - print OUTPUTFILE "$clname:\n\n$hdrline\n\n$cl_entries{$clname}\n"; -} - -if ($inline) { - # Append the patch to the log - foreach (@orig_diff_lines) { - print OUTPUTFILE "$_\n"; - } -} - -if ($inline && $diff ne "-") { - # Close $tmp - close(OUTPUTFILE); - - # Write new contents to $diff atomically - mv $tmp, $diff or die "Could not move temp file to patch file: $!"; -} - -exit 0; + if hunk.ctx_diff: + line = re.sub(r'^([-+! ]) ', r'\1', line) + + # Remember most recent identifier in hunk + # that might be a function name. + if cache.match(r'^[-+! ]([a-zA-Z0-9_#].*)', line): + fn = cache.group(1) + + change = line and re.match(r'^[-+!][^-]', line) + + # Top-level comment can not belong to function + if re.match(r'^[-+! ]\/\*', line): + fn = None + + if change and fn: + if cache.match(r'^((class|struct|union|enum)\s+[a-zA-Z0-9_]+)', fn): + # Struct declaration + fn = cache.group(1) + elif cache.search(r'#\s*define\s+([a-zA-Z0-9_]+)', fn): + # Macro definition + fn = cache.group(1) + elif cache.match('^DEF[A-Z0-9_]+\s*\(([a-zA-Z0-9_]+)', fn): + # Supermacro + fn = cache.group(1) + elif cache.search(r'([a-zA-Z_][^()\s]*)\s*\([^*]', fn): + # Discard template and function parameters. + fn = cache.group(1) + fn = re.sub(r'<[^<>]*>', '', fn) + fn = fn.rstrip() + else: + fn = None + + if fn and fn not in fns: # Avoid dups + fns.append(fn) + + fn = None + + return fns + +def parse_patch(contents): + """Parse patch contents to a sequence of FileDiffs.""" + + diffs = [] + + lines = contents.split('\n') + + i = 0 + while i < len(lines): + line = lines[i] + + # Diff headers look like + # --- a/gcc/tree.c + # +++ b/gcc/tree.c + # or + # *** gcc/cfgexpand.c 2013-12-25 20:07:24.800350058 +0400 + # --- gcc/cfgexpand.c 2013-12-25 20:06:30.612350178 +0400 + + if is_file_diff_start(line): + left = re.split(r'\s+', line)[1] + else: + i += 1 + continue + + left = remove_suffixes(left); + + i += 1 + line = lines[i] + + if not cache.match(r'^[+-][+-][+-] +(\S+)', line): + error("expected filename in line %d" % i) + right = remove_suffixes(cache.group(1)); + + # Extract real file name from left and right names. + filename = None + if left == right: + filename = left + elif left == '/dev/null': + filename = right; + elif right == '/dev/null': + filename = left; + else: + comps = [] + while left and right: + left, l = os.path.split(left) + right, r = os.path.split(right) + if l != r: + break + comps.append(l) + + if not comps: + error("failed to extract common name for %s and %s" % (left, right)) + + comps.reverse() + filename = '/'.join(comps) + + d = FileDiff(filename) + diffs.append(d) + + # Collect hunks for current file. + hunk = None + i += 1 + while i < len(lines): + line = lines[i] + + # Create new hunk when we see hunk header + if is_hunk_start(line): + if hunk is not None: + d.hunks.append(hunk) + hunk = Hunk(line) + i += 1 + continue + + # Stop when we reach next diff + if (is_file_diff_start(line) + or line.startswith('diff ') + or line.startswith('Index: ')): + i -= 1 + break + + if hunk is not None: + hunk.lines.append(line) + i += 1 + + d.hunks.append(hunk) + + return diffs + +def main(): + name, email = read_user_info() + + try: + opts, args = getopt.getopt(sys.argv[1:], 'hiv', ['help', 'verbose', 'inline']) + except getopt.GetoptError, err: + error(str(err)) + + inline = False + verbose = 0 + + for o, a in opts: + if o in ('-h', '--help'): + print_help_and_exit() + elif o in ('-i', '--inline'): + inline = True + elif o in ('-v', '--verbose'): + verbose += 1 + else: + assert False, "unhandled option" + + if len(args) == 0: + args = ['-'] + + if len(args) == 1 and args[0] == '-': + input = sys.stdin + elif len(args) == 1: + input = open(args[0], 'rb') + else: + error("too many arguments; for more details run with -h") + + contents = input.read() + diffs = parse_patch(contents) + + if verbose: + print "Parse results:" + for d in diffs: + d.dump() + + # Generate template ChangeLog. + + logs = {} + for d in diffs: + log_name = d.clname + + logs.setdefault(log_name, '') + logs[log_name] += '\t* %s' % d.relname + + change_msg = '' + + # Check if file was removed or added. + # Two patterns for context and unified diff. + if len(d.hunks) == 1: + hunk0 = d.hunks[0] + if hunk0.is_file_addition(): + if re.search(r'testsuite.*(? + +%s\n""" % (log_name, date, name, email, msg)) + + if inline: + # Append patch body + out.write(contents) + + if args[0] != '-': + # Write new contents atomically + out.close() + shutil.move(tmp, args[0]) + +if __name__ == '__main__': + main() diff --git a/contrib/mklog.pl b/contrib/mklog.pl new file mode 100755 index 0000000000000..ff20cf1ba0f74 --- /dev/null +++ b/contrib/mklog.pl @@ -0,0 +1,362 @@ +#!/usr/bin/perl +# Copyright (C) 2012-2017 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +# This script parses a .diff file generated with 'diff -up' or 'diff -cp' +# and adds a skeleton ChangeLog file to the file. It does not try to be +# very smart when parsing function names, but it produces a reasonable +# approximation. +# +# Author: Diego Novillo and +# Cary Coutant + +use File::Temp; +use File::Copy qw(cp mv); + +$date = `date +%Y-%m-%d`; chop ($date); + +$dot_mklog_format_msg = + "The .mklog format is:\n" + . "NAME = ...\n" + . "EMAIL = ...\n"; + +# Create a .mklog to reflect your profile, if necessary. +my $conf = "$ENV{HOME}/.mklog"; +if (-f "$conf") { + open (CONF, "$conf") + or die "Could not open file '$conf' for reading: $!\n"; + while () { + if (m/^\s*NAME\s*=\s*(.*?)\s*$/) { + $name = $1; + } elsif (m/^\s*EMAIL\s*=\s*(.*?)\s*$/) { + $addr = $1; + } + } + if (!($name && $addr)) { + die "Could not read .mklog settings.\n" + . $dot_mklog_format_msg; + } +} else { + $name = `git config user.name`; + chomp($name); + $addr = `git config user.email`; + chomp($addr); + + if (!($name && $addr)) { + die "Could not read git user.name and user.email settings.\n" + . "Please add missing git settings, or create a .mklog file in" + . " $ENV{HOME}.\n" + . $dot_mklog_format_msg; + } +} + +$gcc_root = $0; +$gcc_root =~ s/[^\\\/]+$/../; + +#----------------------------------------------------------------------------- +# Program starts here. You should not need to edit anything below this +# line. +#----------------------------------------------------------------------------- +$inline = 0; +if ($#ARGV == 1 && ("$ARGV[0]" eq "-i" || "$ARGV[0]" eq "--inline")) { + shift; + $inline = 1; +} elsif ($#ARGV != 0) { + $prog = `basename $0`; chop ($prog); + print <); +close (DFILE); + +# Array diff_lines is modified by the log generation, so save a copy in +# orig_diff_lines if needed. +if ($inline) { + @orig_diff_lines = @diff_lines; +} + +# For every file in the .diff print all the function names in ChangeLog +# format. +%cl_entries = (); +$change_msg = undef; +$look_for_funs = 0; +$clname = get_clname(''); +$line_idx = 0; +foreach (@diff_lines) { + # Stop processing functions if we found a new file. + # Remember both left and right names because one may be /dev/null. + # Don't be fooled by line markers in case of context diff. + if (!/\*\*\*$/ && /^[+*][+*][+*] +(\S+)/) { + $left = remove_suffixes ($1); + $look_for_funs = 0; + } + if (!/---$/ && /^--- +(\S+)?/) { + $right = remove_suffixes ($1); + $look_for_funs = 0; + } + + # Check if the body of diff started. + # We should now have both left and right name, + # so we can decide filename. + + if ($left && (/^\*{15}/ || /^@@ /)) { + # If we have not seen any function names in the previous file (ie, + # $change_msg is empty), we just write out a ':' before starting the next + # file. + if ($clname) { + $cl_entries{$clname} .= $change_msg ? "$change_msg" : ":\n"; + } + + if ($left eq $right) { + $filename = $left; + } elsif($left eq '/dev/null') { + $filename = $right; + } elsif($right eq '/dev/null') { + $filename = $left; + } else { + my @ldirs = split /[\/\\]/, $left; + my @rdirs = split /[\/\\]/, $right; + + $filename = ''; + while ((my $l = pop @ldirs) && (my $r = pop @rdirs)) { + last if ($l ne $r); + $filename = "$l/$filename"; + } + $filename =~ s/\/$//; + + if (!$filename) { + print STDERR "Error: failed to parse diff for $left and $right\n"; + exit 1; + } + } + $left = $right = undef; + ($clname, $relname) = get_clname ($filename); + $cl_entries{$clname} .= "\t* $relname"; + $change_msg = ''; + $look_for_funs = $filename =~ '\.(c|cpp|C|cc|h|inc|def)$'; + } + + # Context diffs have extra whitespace after first char; + # remove it to make matching easier. + if ($is_context_diff) { + s/^([-+! ]) /\1/; + } + + # Remember the last line in a diff block that might start + # a new function. + if (/^[-+! ]([a-zA-Z0-9_].*)/) { + $save_fn = $1; + } + + # Check if file is newly added. + # Two patterns: for context and unified diff. + if (/^\*\*\* 0 \*\*\*\*/ + || /^@@ -0,0 \+1.* @@/) { + $change_msg = $filename =~ /testsuite.*(?]*>//); + $fn =~ s/[ \t]*$//; + } + # Check is function really modified + $no_real_change = 0; + $idx = $line_idx; + # Skip line info in context diffs. + while ($idx <= $#diff_lines && $is_context_diff + && $diff_lines[$idx + 1] =~ /^[-\*]{3} [0-9]/) { + ++$idx; + } + # Check all lines till the first change + # for the presence of really changed function + do { + ++$idx; + $no_real_change = $idx > $#diff_lines + || is_top_level ($diff_lines[$idx], $is_context_diff); + } while (!$no_real_change && ($diff_lines[$idx] !~ /^[-+!]/)); + if ($fn && !$seen_names{$fn} && !$no_real_change) { + # If this is the first function in the file, we display it next + # to the filename, so we need an extra space before the opening + # brace. + if (!$change_msg) { + $change_msg .= " "; + } else { + $change_msg .= "\t"; + } + + $change_msg .= "($fn):\n"; + $seen_names{$fn} = 1; + } + } + $line_idx++; +} + +# If we have not seen any function names (ie, $change_msg is empty), we just +# write out a ':'. This happens when there is only one file with no +# functions. +$cl_entries{$clname} .= $change_msg ? "$change_msg\n" : ":\n"; + +if ($inline && $diff ne "-") { + # Get a temp filename, rather than an open filehandle, because we use + # the open to truncate. + $tmp = mktemp("tmp.XXXXXXXX") or die "Could not create temp file: $!"; + + # Copy the permissions to the temp file (in File::Copy module version + # 2.15 and later). + cp $diff, $tmp or die "Could not copy patch file to temp file: $!"; + + # Open the temp file, clearing contents. + open (OUTPUTFILE, '>', $tmp) or die "Could not open temp file: $!"; +} else { + *OUTPUTFILE = STDOUT; +} + +# Print the log +foreach my $clname (keys %cl_entries) { + print OUTPUTFILE "$clname:\n\n$hdrline\n\n$cl_entries{$clname}\n"; +} + +if ($inline) { + # Append the patch to the log + foreach (@orig_diff_lines) { + print OUTPUTFILE "$_\n"; + } +} + +if ($inline && $diff ne "-") { + # Close $tmp + close(OUTPUTFILE); + + # Write new contents to $diff atomically + mv $tmp, $diff or die "Could not move temp file to patch file: $!"; +} + +exit 0; diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3913f1b37fc6d..3cf1c74b7586f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,2265 @@ +2017-08-29 Uros Bizjak + + * config/i386/i386.opt (flag_fentry): Do not init to -1. + * config/i386/i386.c (ix86_option_override_internal): Simplify + setting of opts->x_flag_entry. + +2017-08-29 Bill Schmidt + Jakub Jelinek + Richard Biener + + PR tree-optimization/81503 + * gimple-ssa-strength-reduction.c (replace_mult_candidate): Ensure + folded constant fits in the target type; reorder tests for clarity. + +2017-08-29 Martin Liska + + * passes.def: Include pass_lower_switch. + * stmt.c (dump_case_nodes): Remove and move to + tree-switch-conversion. + (case_values_threshold): Likewise. + (expand_switch_as_decision_tree_p): Likewise. + (emit_case_decision_tree): Likewise. + (expand_case): Likewise. + (balance_case_nodes): Likewise. + (node_has_low_bound): Likewise. + (node_has_high_bound): Likewise. + (node_is_bounded): Likewise. + (emit_case_nodes): Likewise. + (struct simple_case_node): New struct. + (add_case_node): Remove. + (emit_case_dispatch_table): Use vector instead of case_list. + (reset_out_edges_aux): Remove. + (compute_cases_per_edge): Likewise. + (expand_case): Build list of simple_case_node. + (expand_sjlj_dispatch_table): Use it. + * tree-switch-conversion.c (struct case_node): Moved from + stmt.c and adjusted. + (emit_case_nodes): Likewise. + (node_has_low_bound): Likewise. + (node_has_high_bound): Likewise. + (node_is_bounded): Likewise. + (case_values_threshold): Likewise. + (reset_out_edges_aux): Likewise. + (compute_cases_per_edge): Likewise. + (add_case_node): Likewise. + (dump_case_nodes): Likewise. + (balance_case_nodes): Likewise. + (expand_switch_as_decision_tree_p): Likewise. + (emit_jump): Likewise. + (emit_case_decision_tree): Likewise. + (try_switch_expansion): Likewise. + (do_jump_if_equal): Likewise. + (emit_cmp_and_jump_insns): Likewise. + (fix_phi_operands_for_edge): New function. + (record_phi_operand_mapping): Likewise. + (class pass_lower_switch): New pass. + (pass_lower_switch::execute): New function. + (make_pass_lower_switch): Likewise. + (conditional_probability): + * timevar.def: Add TV_TREE_SWITCH_LOWERING. + * tree-pass.h: Add make_pass_lower_switch. + +2017-08-29 Jozef Lawrynowicz + + PR target/80993 + * gcc/config/msp430/msp430.c (msp430_attr): Mark interrupt + handlers as used. + +2017-08-29 Richard Biener + + * dwarf2out.c (add_dwarf_attr): When checking is enabled verify + we do not add a DW_AT_inline attribute twice. + (gen_subprogram_die): Remove code setting DW_AT_inline on + DECL_ABSTRACT_P nodes. + +2017-08-29 Richard Sandiford + + * gimplify.c (gimplify_call_expr): Copy the nothrow flag to + calls to internal functions. + (gimplify_modify_expr): Likewise. + * tree-call-cdce.c (use_internal_fn): Likewise. + * tree-ssa-math-opts.c (pass_cse_reciprocals::execute): Likewise. + (convert_to_divmod): Set the nothrow flag. + * tree-if-conv.c (predicate_mem_writes): Likewise. + * tree-vect-stmts.c (vectorizable_mask_load_store): Likewise. + (vectorizable_call): Likewise. + (vectorizable_store): Likewise. + (vectorizable_load): Likewise. + * tree-vect-patterns.c (vect_recog_pow_pattern): Likewise. + (vect_recog_mask_conversion_pattern): Likewise. + +2017-08-29 Martin Liska + + PR other/39851 + * gcc.c (driver_handle_option): Add new argument. + * opts-common.c (handle_option): Pass + target_option_override_hook. + * opts-global.c (lang_handle_option): Add new option. + (set_default_handlers): Add new argument. + (decode_options): Likewise. + * opts.c (target_handle_option): Likewise. + (common_handle_option): Call target_option_override_hook. + * opts.h (struct cl_option_handler_func): Add hook for + target option override. + (struct cl_option_handlers): Likewise. + (set_default_handlers): Add new argument. + (decode_options): Likewise. + (common_handle_option): Likewise. + (target_handle_option): Likewise. + * toplev.c (toplev::main): Pass targetm.target_option.override + hook. + +2017-08-29 Richard Biener + Dominik Infuehr + + * tree-vect-slp.c (vect_bb_slp_scalar_cost): Properly confine + life to the active subtree. + +2017-08-28 Jeff Law + + * tree-ssa-dom.c (edge_info::record_simple_equiv): Call + derive_equivalences. + (derive_equivalences_from_bit_ior, record_temporary_equivalences): + Code moved into.... + (edge_info::derive_equivalences): New private member function + + * tree-ssa-dom.c (class edge_info): Changed from a struct + to a class. Add ctor/dtor, methods and data members. + (edge_info::edge_info): Renamed from allocate_edge_info. + Initialize additional members. + (edge_info::~edge_info): New. + (free_dom_edge_info): Delete the edge info. + (record_edge_info): Use new class & associated member functions. + Tighten forms for testing for edge equivalences. + (record_temporary_equivalences): Iterate over the simple + equivalences rather than assuming there's only one per edge. + (cprop_into_successor_phis): Iterate over the simple + equivalences rather than assuming there's only one per edge. + (optimize_stmt): Use operand_equal_p rather than pointer + equality for mini-DSE code. + +2017-08-28 Nathan Sidwell + + * gcc.c (execute): Fold SIGPIPE handling into switch + statement. Adjust internal error message. + +2017-08-28 Richard Biener + + PR debug/81993 + * dwarf2out.c (gen_remaining_tmpl_value_param_die_attributes): + Do nothing for removed DIEs. + +2017-08-28 Richard Biener + + PR tree-optimization/81977 + * tree-ssa-sccvn.c (vn_reference_lookup_3): Fix look through + memcpy. + +2017-08-28 Alexander Monakov + + PR target/80640 + * doc/md.texi (mem_thread_fence): Remove mention of mode. Rewrite. + * optabs.c (expand_mem_thread_fence): Emit a compiler barrier when + using targetm.gen_mem_thread_fence. + +2017-08-27 Uros Bizjak + + PR target/81995 + * config/i386/i386.md (*): Change operand 2 + predicate to register_operand. Reorder operands. + (*btr): Ditto. + (*_mask): Change operand 3 predicate to register_operand. + (*btr_mask): Ditto. + +2017-08-25 Steven Munroe + + * config.gcc (powerpc*-*-*): Add xmmintrin.h and mm_malloc.h. + * config/rs6000/xmmintrin.h: New file. + * config/rs6000/x86intrin.h [__ALTIVEC__]: Include xmmintrin.h. + +2017-08-25 Bill Schmidt + + PR target/81504 + * config/rs6000/rs6000-p8swap.c (find_alignment_op): Add reference + parameter and_insn and return it. + (recombine_lvx_pattern): Insert a copy to ensure availability of + the base register of the copied masking operation at the point of + the instruction replacement. + (recombine_stvx_pattern): Likewise. + +2017-08-25 Michael Meissner + + * config/rs6000/rs6000.opt (-mpower9-dform-scalar): Delete + undocumented switches. + (-mpower9-dform-vector): Likewise. + (-mpower9-dform): Likewise. + * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Update + comments to delete references to -mpower9-dform* switches. + * config/rs6000/predicates.md (vsx_quad_dform_memory_operand): + Delete reference to -mpower9-dform* switches, test for + -mpower9-vector instead. + * config/rs6000/rs6000-cpus.def (ISA_3_0_MASKS_SERVER): Likewise. + (OTHER_P9_VECTOR_MASKS): Likewise. + (POWERPC_MASKS): Likewise. + * config/rs6000/rs6000.c (rs6000_setup_reg_addr_masks): Change + tests against -mpower9-dform* to -mpower9-vector. Delete code + that checked for -mpower9-dform* consistancy with other options. + Add test for -mpower9-misc to enable other power9 switches. + (rs6000_init_hard_regno_mode_ok): Likewise. + (rs6000_option_override_internal): Likewise. + (rs6000_emit_prologue): Likewise. + (rs6000_emit_epilogue): Likewise. + (rs6000_opt_masks): Delete -mpower9-dform-{scalar,vector}. + (rs6000_disable_incompatiable_switches): Delete -mpower9-dform. + (emit_fusion_p9_load): Change tests for -mpower9-dform-scalar + -mpower9-vector. + (emit_fusion_p9_store): Likewise. + * config/rs6000/rs6000.h (TARGET_P9_DFORM_SCALAR): Delete + resetting these macros if the assembler does not support ISA 3.0 + instructions. + (TARGET_P9_DFORM_VECTOR): Likewise. + * config/rs6000/rs6000.md (peepholes to optimize altivec memory): + Change to use -mpower9-vector instead of -mpower9-dform-scalar. + +2017-08-25 Alan Modra + + PR rtl-optimization/81747 + * cse.c (cse_extended_basic_block): Don't attempt to record + equivalences for degenerate conditional branches that branch + to their fall-through. + +2017-08-24 Martin Sebor + + PR middle-end/81908 + * gimple-fold.c (size_must_be_zero_p): New function. + (gimple_fold_builtin_memory_op): Call it. + +2017-08-24 Steven Munroe + + * config/rs6000/mm_malloc.h: New file. + +2017-08-24 Bin Cheng + + PR tree-optimization/81913 + * tree-ssa-loop-niter.c (number_of_iterations_cond): Skip niter + analysis when either IVs in condition can wrap. + +2017-08-24 Uros Bizjak + + * dwarf2out.c (MAX_ARTIFICIAL_LABEL_BYTES): Increase to 40. + * dwarf2cfi.c (MAX_ARTIFICIAL_LABEL_BYTES): Remove. + +2017-08-24 Richard Biener + + PR target/81921 + * targhooks.c (default_target_can_inline_p): Properly + use target_option_default_node when no DECL_FUNCTION_SPECIFIC_TARGET + is present and always compare. + * config/i386/i386.c (ix86_valid_target_attribute_tree): Do not + infer -mfpmath=sse from TARGET_SSE_P. + (ix86_can_inline_p): Properly use target_option_default_node when + no DECL_FUNCTION_SPECIFIC_TARGET is present and always compare. + +2017-08-24 Richard Biener + + PR debug/81936 + * dwarf2out.c (output_die): Handle flag_generate_offload like + flag_generate_lto. + (output_comp_unit): Likewise. + (gen_array_type_die): Likewise. + (dwarf2out_early_finish): Likewise. + (note_variable_value_in_expr): Likewise. + (dwarf2out_finish): Likewise. Adjust assert. + * cgraphunit.c (symbol_table::compile): Move setting of + flag_generate_offload earlier ... + (symbol_table::finalize_compilation_unit): ... here, before + early debug finalization. + +2017-08-24 Richard Biener + + * config/i386/i386.c: Include symbol-summary.h, ipa-prop.h + and ipa-fnsummary.h. + (ix86_can_inline_p): When ix86_fpmath flags do not match + check whether the callee uses FP math at all. + +2017-08-24 Aldy Hernandez + + PR middle-end/81931 + * tree-ssanames.c (get_nonzero_bits): Use element_precision + instead of TYPE_PRECISION. + +2017-08-24 Richard Sandiford + Alan Hayward + David Sherwood + + * combine.c (make_extraction): Use subreg_offset_from_lsb. + +2017-08-23 Daniel Santos + + * config/i386/i386.h (ix86_frame::stack_realign_allocate_offset): + Remove field. + (ix86_frame::stack_realign_allocate): New field. + (struct machine_frame_state): Modify comments. + (machine_frame_state::sp_realigned_fp_end): New field. + * config/i386/i386.c (ix86_compute_frame_layout): Rework stack frame + layout calculation. + (sp_valid_at): Add assertion to assure no attempt to access invalid + offset of a realigned stack. + (fp_valid_at): Likewise. + (choose_baseaddr): Modify comments. + (ix86_emit_outlined_ms2sysv_save): Adjust to changes in + ix86_expand_prologue. + (ix86_expand_prologue): Modify stack realignment and allocation. + (ix86_expand_epilogue): Modify comments. + * doc/sourcebuild.texi: Add documentation for target selectors avx2, + avx2_runtime, avx512f, and avx512f_runtime. + +2017-08-23 Uros Bizjak + + * config/i386/i386.opt: Remove unneeded Init(0) initializations. + (mstackrealign): Do not init to -1. + * config/i386/i386.c (ix86_option_override_internal): + Check opts_set, not opts when setting default value of + opts->x_ix86_force_align_arg_pointer. + +2017-08-23 Richard Biener + + * function.c (fndecl_name): Use verbosity 1 (no arguments) for + lang_hooks.decl_printable_name. + * print-rtl-function.c (print_rtx_function): Likewise. + * tree-pretty-print.c (dump_function_header): Likewise. + +2017-08-23 Richard Biener + + PR lto/81940 + * dwarf2out.c (dwarf2out_abstract_function): Handle LTO with + -g0 at compile-time. + +2017-08-23 Tamar Christina + + PR middle-end/19706 + * doc/sourcebuild.texi (Other hardware attributes): + Document xorsign. + +2017-08-23 Tamar Christina + + PR middle-end/19706 + * tree-ssa-math-opts.c (convert_expand_mult_copysign): + Fix single-use check. + +2017-08-23 Thomas Preud'homme + + * gcc.c (execute): Only test for SIGKILL and SIGQUIT if available. + +2017-08-22 Daniel Santos + + * doc/install.texi: Modify to add more details on running selected + tests. + +2017-08-22 Daniel Santos + + * config/i386/i386.c (ix86_option_override_internal): Error when -mx32 + is combined with -mabi=ms. + (ix86_function_type_abi): Limit errors for mixing -mx32 with attribute + ms_abi. + +2017-08-22 Bill Schmidt + + PR tree-optimization/81488 + * gimple-ssa-strength-reduction (struct slsr_cand_d): Add visited + and cached_basis fields. + (MAX_SPREAD): New constant. + (alloc_cand_and_find_basis): Initialize new fields. + (clear_visited): New function. + (create_phi_basis_1): Rename from create_phi_basis, set visited + and cached_basis fields. + (create_phi_basis): New wrapper function. + (phi_add_costs_1): Rename from phi_add_costs, add spread + parameter, set visited field, short-circuit when limits reached. + (phi_add_costs): New wrapper function. + (record_phi_increments_1): Rename from record_phi_increments, set + visited field. + (record_phi_increments): New wrapper function. + (phi_incr_cost_1): Rename from phi_incr_cost, set visited field. + (phi_incr_cost): New wrapper function. + (all_phi_incrs_profitable_1): Rename from + all_phi_incrs_profitable, set visited field. + (all_phi_incrs_profitable): New wrapper function. + +2017-08-22 Richard Sandiford + Alan Hayward + David Sherwood + + * rtl.h (paradoxical_subreg_p): Define inline, and add a version + that takes the outer and inner modes. + * doc/rtl.texi: Use paradoxical_subreg_p instead of a GET_MODE_SIZE + comparison as the canonical test for a paradoxical subreg. + * combine.c (simplify_set): Use paradoxical_subreg_p. + (make_extraction): Likewise. + (force_to_mode): Likewise. + (rtx_equal_for_field_assignment_p): Likewise. + (gen_lowpart_for_combine): Likewise. + (simplify_comparison): Likewise. + * cse.c (equiv_constant): Likewise. + * expmed.c (store_bit_field_1): Likewise. + * final.c (alter_subreg): Likewise. + * fwprop.c (propagate_rtx): Likewise. + (forward_propagate_subreg): Likewise. + * ira-conflicts.c (ira_build_conflicts): Likewise. + * lower-subreg.c (simplify_gen_subreg_concatn): Likewise. + * lra-constraints.c (curr_insn_transform): Likewise. + (split_reg): Likewise. + * lra-eliminations.c (move_plus_up): Likewise. + (lra_eliminate_regs_1): Likewise. + * recog.c (general_operand): Likewise. + * ree.c (combine_reaching_defs): Likewise. + * reload.c (push_reload): Likewise. + (find_reloads): Likewise. + * reload1.c (elimination_effects): Likewise. + (compute_reload_subreg_offset): Likewise. + (choose_reload_regs): Likewise. + * rtlanal.c (subreg_lsb_1): Likewise. + * simplify-rtx.c (simplify_unary_operation_1): Likewise. + (simplify_subreg): Likewise. + * var-tracking.c (track_loc_p): Likewise. + * emit-rtl.c (byte_lowpart_offset): Likewise. + (paradoxical_subreg_p): Delete out-of-line definition. + +2017-08-22 Jeff Law + + PR tree-optimization/81741 + PR tree-optimization/71947 + * tree-ssa-dom.c: Include tree-inline.h. + (record_temporary_equivalences): Only record SSA_NAME = SSA_NAME + equivalences if one is more expensive to compute than the other. + * tree-ssa-scopedtables.h (class const_or_copies): Make + record_const_or_copy_raw method private. + (class avail_exprs_stack): New method simplify_binary_operation. + * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr): Call + avail_exprs_stack::simplify_binary_operation as needed. + (avail_exprs_stack::simplify_binary_operation): New function. + +2017-08-22 Sebastian Huber + + * config.gcc (powerpc-*-rtems*): Add rs6000/linux64.opt. + * config/rs6000/rtems.h (ASM_PREFERRED_EH_DATA_FORMAT): New define. + (DOT_SYMBOLS): Likewise. + (MINIMAL_TOC_SECTION_ASM_OP): Likewise. + (RELOCATABLE_NEEDS_FIXUP): Likewise. + (RS6000_ABI_NAME): Likewise. + (TARGET_CMODEL): Likewise. + (TOC_SECTION_ASM_OP): Likewise. + (SET_CMODEL): New macro. + (SUBSUBTARGET_OVERRIDE_OPTIONS): Evaluate cmodel options. + +2017-08-22 Richard Biener + + * tree-inline.c (remap_type_1): Change asserts on TYPE_SIZE[_UNIT] + to allow for free-lang-data replacements similar to verify_type_variant. + +2017-08-22 Richard Sandiford + Alan Hayward + David Sherwood + + * config/aarch64/aarch64.md (casesi): Use DImode rather than + VOIDmode for the LABEL_REF. + +2017-08-22 Richard Biener + + * tree-cfg.c (gimple_split_edge): Avoid reallocating target PHI nodes. + +2017-08-22 Richard Biener + + * common.opt (feliminate-dwarf2-dups): Ignore. + * doc/invoke.texi (feliminate-dwarf2-dups): Remove documentation. + * dwarf2out.c (push_new_compile_unit, pop_compile_unit, + same_die_p_wrap, compute_section_prefix, + is_symbol_die, assign_symbol_names, break_out_includes): Remove. + (comdat_symbol_id, comdat_symbol_number): Likewise. + (cu_hash_table_entry, cu_hash_table_entry_hasher, cu_hash_type): + Likewise. + (check_duplicate_cu, record_comdat_symbol_number): Likewise. + (output_die): Mark unreachable path unreachable. + (dwarf2out_start_source_file): Do not create DW_TAG_GNU_BINCL. + (dwarf2out_end_source_file): Do not create DW_TAG_GNU_EINCL. + (dwarf2out_init): Remove code handling flag_eliminate_dwarf2_dups. + (dwarf2out_early_finish): Likewise. + +2017-08-22 Aldy Hernandez + + * wide-int.h (hwi_with_prec::hwi_with_prec): Sign extend. + +2017-08-22 Georg-Johann Lay + + PR target/81910 + * config/avr/avr.c (avr_handle_addr_attribute): Early return if + not VAR_P. Filter attribute warnings with OPT_Wattributes. + (avr_attribute_table) : Initialize + .decl_required with true. + +2017-08-21 Michael Meissner + + * config/rs6000/rs6000-cpus.def (-mvsx-scalar-float): Delete + undocumented debugging options. + (-mvsx-scalar-double): Likewise. + (-mallow-df-permute): Likewise. + (-mvectorize-builtins): Likewise. + * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Likewise. + (rs6000_builtin_vectorized_function): Likewise. + (rs6000_builtin_md_vectorized_function): Likewise. + (rs6000_opt_vars): Likewise. + +2017-08-21 Uros Bizjak + + PR target/46091 + * config/i386/i386.md (*btsq_imm): Rename from *btsq. + (*btrq_imm): Rename from *btrq. + (*btcq_imm): Rename from *btcq. + (btsc): New code attribute. + (*): New insn pattern. + (*btr): Ditto. + (*_mask): New insn_and_split pattern. + (*btr_mask): Ditto. + +2017-08-21 Richard Sandiford + Alan Hayward + David Sherwood + + * function.c (pad_below): Simplify padding calculation. + +2017-08-21 Richard Sandiford + Alan Hayward + David Sherwood + + * target.def (function_prologue): Remove frame size argument. + (function_epilogue): Likewise. + * doc/tm.texi: Regenerate. + * final.c (final_start_function): Update call to function_prologue. + (final_end_function): Update call to function_epilogue. + (default_function_pro_epilogue): Remove frame size argument. + * output.h (default_function_pro_epilogue): Likewise. + * config/arm/arm.c (arm_output_function_epilogue): Likewise. + (arm_output_function_prologue): Likewise. + * config/frv/frv.c (frv_function_prologue): Likewise. + (frv_function_epilogue): Likewise. + * config/i386/i386.c (ix86_output_function_epilogue): Likewise. + * config/ia64/ia64.c (ia64_output_function_prologue): Likewise. + (ia64_output_function_epilogue): Likewise. + * config/m32r/m32r.c (m32r_output_function_prologue): Likewise. + (m32r_output_function_epilogue): Likewise. + * config/microblaze/microblaze.c (microblaze_function_prologue) + (microblaze_function_epilogue): Likewise. + * config/mips/mips.c (mips_output_function_prologue): Likewise. + (mips_output_function_epilogue): Likewise. + * config/mmix/mmix.c (mmix_target_asm_function_prologue): Likewise. + (mmix_target_asm_function_epilogue): Likewise. + * config/msp430/msp430.c (msp430_start_function): Likewise. + * config/nds32/nds32.c (nds32_asm_function_prologue): Likewise. + (nds32_asm_function_epilogue): Likewise. + * config/nios2/nios2.c (nios2_asm_function_prologue): Likewise. + * config/pa/pa.c (pa_output_function_prologue): Likewise. + (pa_output_function_epilogue): Likewise. + * config/powerpcspe/powerpcspe.c (rs6000_output_function_prologue) + (rs6000_output_function_epilogue): Likewise. + * config/rl78/rl78.c (rl78_start_function): Likewise. + * config/rs6000/rs6000.c (rs6000_output_function_prologue): Likewise. + (rs6000_output_function_epilogue): Likewise. + * config/rx/rx.c (rx_output_function_prologue): Likewise. + * config/sh/sh.c (sh_output_function_epilogue): Likewise. + * config/sparc/sparc.c (sparc_asm_function_prologue): Likewise. + (sparc_asm_function_epilogue): Likewise. + +2017-08-21 Richard Sandiford + + * tree.h (type_has_mode_precision_p): New function. + * convert.c (convert_to_integer_1): Use it. + * expr.c (expand_expr_real_2): Likewise. + (expand_expr_real_1): Likewise. + * fold-const.c (fold_single_bit_test_into_sign_test): Likewise. + * match.pd: Likewise. + * tree-ssa-forwprop.c (simplify_rotate): Likewise. + * tree-ssa-math-opts.c (convert_mult_to_fma): Likewise. + * tree-tailcall.c (process_assignment): Likewise. + * tree-vect-loop.c (vectorizable_reduction): Likewise. + * tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern) + (vect_recog_mult_pattern, vect_recog_divmod_pattern): Likewise. + * tree-vect-stmts.c (vectorizable_conversion): Likewise. + (vectorizable_assignment): Likewise. + (vectorizable_shift): Likewise. + (vectorizable_operation): Likewise. + * tree-vrp.c (register_edge_assert_for_2): Likewise. + +2017-08-21 Wilco Dijkstra + + * match.pd: Add pow (C, x) simplification. + +2017-08-21 Richard Biener + + PR tree-optimization/81900 + * tree-ssa-pre.c (compute_antic_aux): Properly compute changed + for blocks with abnormal predecessors. + (compute_antic): Do not set visited flag prematurely. + +2017-08-21 Georg-Johann Lay + + PR target/79883 + * config/avr/avr.c (avr_set_current_function): Typo in diagnostic. + +2017-08-21 Richard Sandiford + + * stor-layout.h (vector_type_mode): Move to... + * tree.h (vector_type_mode): ...here. + * stor-layout.c (vector_type_mode): Move to... + * tree.c (vector_type_mode): ...here. Include rtl.h and regs.h. + +2017-08-21 Richard Biener + + * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and + register_external_die hooks. + (debug_false_tree_charstarstar_uhwistar): Declare. + (debug_nothing_tree_charstar_uhwi): Likewise. + * debug.c (do_nothing_debug_hooks): Adjust. + (debug_false_tree_charstarstar_uhwistar): New do nothing. + (debug_nothing_tree_charstar_uhwi): Likewise. + * dbxout.c (dbx_debug_hooks): Adjust. + (xcoff_debug_hooks): Likewise. + * sdbout.c (sdb_debug_hooks): Likewise. + * vmsdbgout.c (vmsdbg_debug_hooks): Likewise. + * dwarf2out.c (macinfo_label_base): New global. + (dwarf2out_register_external_die): New function for the + register_external_die hook. + (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl. + (dwarf2_debug_hooks): Use them. + (dwarf2_lineno_debug_hooks): Adjust. + (struct die_struct): Add with_offset flag. + (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION, + DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION, + DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION, + DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION, + DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION, + DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros + defining section names for the early LTO debug variants. + (reset_indirect_string): New helper. + (add_AT_external_die_ref): Helper for dwarf2out_register_external_die. + (print_dw_val): Add support for offsetted symbol references. + (get_ultimate_context): Split out from is_cxx. + (is_cxx): Use get_ultimate_context. + (is_fortran): Add decl overload. + (compute_comp_unit_symbol): Split out worker from + compute_section_prefix. + (compute_section_prefix): Call compute_comp_unit_symbol and + set comdat_type_p here. + (output_die): Skip DIE symbol output for the LTO added one. + Handle DIE symbol references with offset. + (output_comp_unit): Guard section name mangling properly. + For LTO debug sections emit a symbol at the section beginning + which we use to refer to its DIEs. + (add_abstract_origin_attribute): For DIEs registered via + dwarf2out_register_external_die directly refer to the early + DIE rather than indirectly through the shadow one we created. + Remove obsolete call to dwarf2out_abstract_function for + non-function/block origins. + (gen_array_type_die): When generating early LTO debug do + not emit DW_AT_string_length. + (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs + late when in LTO. As suggested place a gcc_unreachable for + the DECL_ABSTRACT_P case. + (gen_subprogram_die): Avoid another specification DIE + for early built declarations/definitions for the late LTO case. + (gen_variable_die): Add type references for late duplicated VLA dies + when in late LTO. + (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function, + we have the abstract instance already. + (process_scope_var): Adjust decl DIE contexts in LTO which + first puts them in limbo. + (gen_decl_die): Do not generate type DIEs late apart from + types for VLAs or for decls we do not yet have a DIE. Do not + call dwarf2out_abstract_function late. + (dwarf2out_early_global_decl): Make sure to create DIEs + for abstract instances of a decl first. + (dwarf2out_late_global_decl): Adjust comment. + (output_macinfo_op): With multiple macro sections use + macinfo_label_base to distinguish labels. + (output_macinfo): Likewise. Update macinfo_label_base. + Pass in the line info label. + (note_variable_value_in_expr): When generating LTO resolve + all variable values here by generating DIEs as needed. + (init_sections_and_labels): Add early LTO debug flag parameter + and generate different sections and names if set. Add generation + counter for the labels so we can have multiple of them. + (reset_dies): Helper to allow DIEs to be output multiple times. + (dwarf2out_finish): When outputting DIEs to the fat part of an + LTO object first reset DIEs. + (dwarf2out_early_finish): Output early DIEs when generating LTO. + (modified_type_die): Check for decl_ultimate_origin being self + before recursing. + (gen_type_die_with_usage): Likewise. + (gen_typedef_die): Allow decl_ultimate_origin being self. + (set_decl_abstract_flags): Remove. + (set_block_abstract_flags): Likewise. + (dwarf2out_abstract_function): Treat the early generated DIEs + as the abstract copy and only add DW_AT_inline and + DW_AT_artificial here and call set_decl_origin_self. + If the DIE has an abstract origin don't do anything. + * tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL + if we have none yet (Go fails to build one, PR78628). + (variably_modified_type_p): Prevent endless recursion for Ada + cyclic pointer types. + * lto-streamer-in.c: Include debug.h. + (dref_queue): New global. + (lto_read_tree_1): Stream in DIE references. + (lto_input_tree): Register DIE references. + (input_function): Stream DECL_DEBUG_ARGS. + * lto-streamer-out.c: Include debug.h. + (lto_write_tree_1): Output DIE references. + (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN. + Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls. + (output_function): Stream DECL_DEBUG_ARGS. + * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers): + Stream DECL_ABSTRACT_ORIGIN. + * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise. + (write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL + DECL_CONTEXT for file-scope decls. + * lto-streamer.h (struct dref_entry): Declare. + (dref_queue): Likewise. + * cfgexpand.c (pass_expand::execute): Do not call the + outlining_inline_function hook here. + * lto-wrapper.c (debug_obj): New global. + (tool_cleanup): Unlink it if required. + (debug_objcopy): New function. + (run_gcc): Handle early debug sections in the IL files by + extracting them to separate files, partially linkin them and + feeding the result back as result to the linker. + * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION, + DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION, + DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug + sections into a separate segment. + * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO + segments. + (darwin_asm_dwarf_section): Likewise. + (darwin_asm_output_dwarf_offset): Likewise. + * config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P. + +2017-08-21 Richard Sandiford + Alan Hayward + David Sherwood + + * read-md.h (md_reader::record_potential_iterator_use): Replace + pointer argument with an rtx and an index. + * read-rtl.c (iterator_group::apply_iterator): Likewise. + (apply_mode_iterator): Likewise. + (apply_code_iterator): Likewise. + (apply_int_iterator): Likewise. + (apply_subst_iterator): Likewise. + (record_iterator_use): Likewise. + (record_attribute_use): Likewise. + (md_reader::record_potential_iterator_use): Likewise. Update calls + to record_iterator_use and apply_iterator. + (iterator_use): Replace ptr with x and index. + (attribute_use): Likewise. + (apply_attribute_uses): Update calls to apply_iterator. + (apply_iterators): Likewise. Update initialization of iterator_use. + (rtx_reader::read_rtx_code): Update calls to record_iterator_use + and record_potential_iterator_use. + (rtx_reader::read_rtx_operand): Likewise. + +2017-08-21 Richard Sandiford + Alan Hayward + David Sherwood + + * varasm.c (const_rtx_hash_1): Don't hash in the mode of a + CONST_WIDE_INT. + +2017-08-21 Richard Biener + + PR middle-end/81884 + * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses + at struct end conservatively when comparing common bases. + +2017-08-21 Richard Biener + + * tree-ssa-loop-im.c (struct lim_aux_data): Add ref index member. + (mem_ref_in_stmt): Remove. + (determine_max_movement): Use ref index to get at the reference. + (invariantness_dom_walker::before_dom_children): Deal with + lim data already initialized. + (gather_mem_refs_stmt): Initialize lim data and record ref index. + +2017-08-19 Uros Bizjak + + * config/i386/i386.h (OPTION_MASK_ISA_ROUND): Remove. + (TARGET_ISA_ROUND): Ditto. + (TARGET_ROUND): Ditto. + * config/i386/i386.c: Substitute TARGET_ROUND with TARGET_SSE4_1. + * config/i386/i386.md: Ditto. + * config/i386/sse.md: Ditto. + * config/i386/i386-builtin.def: Substitute OPTION_MASK_ISA_ROUND + with OPTION_MASK_ISA_SSE4_1. + +2017-08-19 Uros Bizjak + + PR target/81894 + * doc/extend.texi (x86 Built-in Functions): Correct the name of + __builtin_ia32_lzcnt_u16. + +2017-08-18 Peter Bergner + + PR target/80210 + * config/rs6000/rs6000.c (rs6000_activate_target_options): New function. + (rs6000_set_current_function): Rewrite function to use it. + +2017-08-18 H.J. Lu + + PR c/53037 + * print-tree.c (print_node): Support DECL_WARN_IF_NOT_ALIGN + and TYPE_WARN_IF_NOT_ALIGN. + * stor-layout.c (do_type_align): Merge DECL_WARN_IF_NOT_ALIGN. + (handle_warn_if_not_align): New. + (place_union_field): Call handle_warn_if_not_align. + (place_field): Call handle_warn_if_not_align. + Copy TYPE_WARN_IF_NOT_ALIGN. + (finish_builtin_struct): Copy TYPE_WARN_IF_NOT_ALIGN. + (layout_type): Likewise. + * tree-core.h (tree_type_common): Add warn_if_not_align. Set + spare to 18. + (tree_decl_common): Add warn_if_not_align. + * tree.c (build_range_type_1): Copy TYPE_WARN_IF_NOT_ALIGN. + * tree.h (TYPE_WARN_IF_NOT_ALIGN): New. + (SET_TYPE_WARN_IF_NOT_ALIGN): Likewise. + (DECL_WARN_IF_NOT_ALIGN): Likewise. + (SET_DECL_WARN_IF_NOT_ALIGN): Likewise. + * doc/extend.texi: Document warn_if_not_aligned attribute. + * doc/invoke.texi: Document -Wif-not-aligned and -Wpacked-not-aligned. + +2017-08-17 Martin Liska + + PR bootstrap/81864 + * tree-loop-distribution.c (ddrs_table): Change type to pointer type. + (get_data_dependence): Use it as pointer type. + (distribute_loop): Likewise. + +2017-08-17 Bill Schmidt + + * config/rs6000/altivec.md (UNSPEC_VMRGOW_DIRECT): New constant. + (p8_vmrgew_v4sf_direct): Generalize to p8_vmrgew__direct. + (p8_vmrgow__direct): New define_insn. + * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Properly + handle endianness for vmrgew and vmrgow permute patterns. + +2017-08-17 Peter Bergner + + * config/rs6000/altivec.md (VParity): Remove TARGET_VSX_TIMODE. + * config/rs6000/rs6000-cpus.def: Remove comment. + (ISA_2_7_MASKS_SERVER): Delete OPTION_MASK_VSX_TIMODE; + (POWERPC_MASKS): Likewise. + * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Remove unneeded + use of TARGET_VSX_TIMODE. + (rs6000_setup_reg_addr_masks): Change TARGET_VSX_TIMODE to TARGET_VSX. + (rs6000_init_hard_regno_mode_ok): Remove unneeded uses of + TARGET_VSX_TIMODE. Change use of TARGET_VSX_TIMODE to TARGET_VSX. + (rs6000_option_override_internal): Remove dead code. + (rs6000_legitimize_address): Change TARGET_VSX_TIMODE to TARGET_VSX. + (rs6000_legitimize_reload_address): Likewise. + (rs6000_legitimate_address_p): Likewise. + (rs6000_opt_masks): Delete "vsx-timode". + (rs6000_disable_incompatible_switches): Remove mention of -mvsx-timode + from function comment. + * config/rs6000/rs6000.h (MASK_VSX_TIMODE): Delete. + * config/rs6000/rs6000.md (FMOVE128_GPR): Remove TARGET_VSX_TIMODE. + (V16QI, V8HI, V4SI, V4SF, V2DI, V2DF, V1TI): Remove useless empty + condition. + * config/rs6000/rs6000.opt (mvsx-timode): Replace with stub. + * config/rs6000/vector.md (VEC_IP): Remove TARGET_VSX_TIMODE. + * config/rs6000/vsx.md (VSX_LE_128): Likewise. + (VSX_TI): Likewise. + (VSX_M): Likewise. + (define_peephole2): Likewise. + +2017-08-17 Martin Sebor + + PR c/81859 + * pretty-print.c (pp_format): Use strnlen in %.*s to avoid reading + past the end of an array. + (test_pp_format): Add test cases. + +2017-08-17 Richard Sandiford + + * internal-fn.def (CLRSB, CLZ, CTZ, FFS, PARITY, POPCOUNT): Add + missing ECF_NOTHROW flags. + +2017-08-17 Peter Bergner + + PR target/72804 + * config/rs6000/vsx.md (*vsx_le_permute_): Add support for + operands residing in integer registers. + (*vsx_le_perm_load_): Likewise. + (*vsx_le_perm_store_): Likewise. + (define_peephole2): Add peepholes to optimize the above. + +2017-08-17 Marek Polacek + + PR middle-end/81814 + * fold-const.c (operand_equal_for_comparison_p): Remove code that used + to mimic what shorten_compare did. Change the return type to bool. + (fold_cond_expr_with_comparison): Update call to + operand_equal_for_comparison_p. + (fold_ternary_loc): Likewise. + +2017-08-17 Jackson Woodruff + + * aarch64-simd.md (mov): No longer force zero immediate into + register. + (*aarch64_simd_mov): Add new case for stp using zero immediate. + +2017-08-17 Richard Biener + + * tree-ssa-structalias.c (solve_graph): When propagating + to successors update the graphs succ edges and avoid duplicate work. + +2017-08-17 Maxim Ostapenko + + PR target/81861 + * config/i386/i386.c (ix86_option_override_internal): Save target + specific options after ix86_stack_protector_guard_reg was changed. + +2017-08-17 Richard Biener + + PR tree-optimization/81827 + * tree-ssa-structalias.c (struct variable_info): Add is_reg_var flag. + (new_var_info): Initialize it conservatively. + (get_call_vi): Mark register vars. + (new_scalar_tmp_constraint_exp): Likewise. + (handle_rhs_call): Likewise. + (handle_const_call): Likewise. + (create_function_info_for): Likewise. + (solve_constraints): Sort varinfos to separate register from + non-register vars to pack points-to solution bitmaps during + iteration. + +2017-08-17 Marek Polacek + + * gimplify.c (gimplify_adjust_omp_clauses): Compare with 0 instead of 1. + +2017-08-17 Richard Biener + + * tree-vrp.c (vrp_int_const_binop): Do not set *overflow_p + to true when overflow is undefined and we saturated the result. + +2017-08-17 Alan Modra + + PR target/80938 + * config/rs6000/rs6000.c (rs6000_savres_strategy): Revert 2017-08-09. + Don't use store multiple if only one reg needs saving. + (interesting_frame_related_regno): New function. + (rs6000_frame_related): Don't emit frame info for regs that + don't need saving. + (rs6000_emit_epilogue): Likewise. + +2017-08-16 Nathan Sidwell + + * tree-core.h (tree_type_non_common): Rename binfo to lang_1. + * tree.h (TYPE_BINFO): Use type_non_common.maxval. + (TYPE_LANG_SLOT_1): Use type_non_common.lang_1, for any type. + * tree.c (free_lang_data_in_type): Use else-if chain. Always + clear TYPE_LANG_1. Remove obsolete member-function stripping. + (find_decls_types_r): Comment about TYPE_MAX_VALUES_RAW. + (verify_type): Adjust for TYPE_BINFO move. + * lto-streamer-out.c (DFS::DFS_write_tree_body): No need to + process TYPE_BINFO directly. + (hash_tree): Likewise. + * tree-streamer-in.c (lto_input_ts_type_non_common_tree_pointers): + Likewise. + * tree-streamer-out.c (write_ts_type_non_common_tree_pointers): + Likewise. + +2017-08-16 David Malcolm + + * diagnostic-show-locus.c (colorizer::m_caret): Remove unused field. + +2017-08-16 Uros Bizjak + + PR target/46091 + * config/i386/i386.md (*anddi_1_btr): Change predicates of + operand 0 and operand 1 to nomimmediate_operand. Add "m" constraint. + Add ix86_binary_operator_ok to insn constraint. + (*iordi_1_bts): Ditto. + (*xordi_1_btc): Ditto. + (*btsq): Change predicate of operand 0 to nonimmediate_operand. + Update corresponding peephole2 pattern. + (*btrq): Ditto. + (*btcq): Ditto. + +2017-08-16 Bin Cheng + + PR tree-optimization/81832 + * tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Don't + copy loop header which has IFN_LOOP_DIST_ALIAS call. + +2017-08-16 Marek Polacek + + PR middle/81695 + * fold-const.c (fold_indirect_ref_1): Restore original behavior + regarding size_zero_node. + +2017-08-16 Martin Liska + + PR target/81753 + * config.gcc: Respect previously set extra_objs in case + of darwin target. + +2017-08-16 Richard Sandiford + + PR tree-optimization/81835 + * tree-vect-loop.c (vect_is_simple_reduction): Simply checks for + the phi SSA_NAME. Check that the condition in a COND_EXPR does + not depend on the phi. + +2017-08-16 Alan Modra + + * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Delete + dead code. + +2017-08-16 Alan Modra + + * config/rs6000/rs6000.c (rs6000_reg_live_or_pic_offset_p): Merge.. + (save_reg_p): ..into this. Update all callers. + (first_reg_to_save): Simplify. + +2017-08-16 Alan Modra + + * config/rs6000/rs6000.c (rs6000_savres_strategy): Don't restore + fixed regs. + +2017-08-15 Joseph Myers + + PR target/78460 + PR target/67712 + * config/sh/sh-mem.cc (sh_expand_cmpnstr): Only unroll for + constant count if that count is less than 32. + +2017-08-15 Nathan Sidwell + + * gcc.c (execute): Emit friendlier message if inferior is killed + by an external cause. + +2017-08-15 Richard Biener + + PR tree-optimization/81790 + * tree-ssa-sccvn.c (vn_lookup_simplify_result): Handle both + CONSTRUCTORs from simplifying and VN. + +2017-08-14 Martin Sebor + + * builtin-attrs.def: Add comments. + +2017-08-14 Martin Sebor + + PR c/81117 + * doc/extend.texi (attribute nonstring): Document new attribute. + +2017-08-14 Martin Sebor + + PR c/81117 + * tree-diagnostic.c (default_tree_printer): Handle %G. + * gimple-pretty-print.h (percent_G_format): Declare new function. + * gimple-pretty-print.c (percent_G_format): Define. + * tree-pretty-print.c (percent_K_format): Add argument. + +2017-08-14 Martin Sebor + + PR translation/79998 + * gimple-ssa-sprintf.c (pass_sprintf_length::handle_gimple_call): + Remove a stray space. + +2017-08-14 Uros Bizjak + + PR target/46091 + * config/i386/i386.md (*anddi_1_btr): New insn_and_split pattern. + (*iordi_1_bts): Ditto. + (*xordi_1_btc): Ditto. + +2017-08-14 Bill Schmidt + + PR target/79845 + * config/rs6000/linux64.h (INVALID_64BIT): Use quoted strings. + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): + Likewise. + * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Use + quoted strings, and make more translator-friendly. + (darwin_rs6000_override_options): Likewise. + (rs6000_option_override_internal): Likewise. + (rs6000_return_in_memory): Fix overlong line. + (init_cmulative_args): Use quoted strings, and make more + translator-friendly. + (rs6000_pass_by_reference): Fix overlong line. + (def_builtin): Use quoted strings. + (altivec_expand_predicate_builtin): Use quoted strings, and make + more translator-friendly. + (htm_expand_builtin): Use quoted strings. + (cpu_expand_builtin): Use quoted strings, and make more + translator-friendly. + (altivec_expand_builtin): Likewise. + (paired_expand_predicate_builtin): Likewise. + (rs6000_invalid_builtin): Likewise. + (builtin_function_type): Use quoted strings. + (rs6000_expand_split_stack_prologue): Use quoted strings, and make + more translator-friendly. + (rs6000_trampoline_init): Likewise. + (rs6000_handle_altivec_attribute): Likewise. + (rs6000_inner_target_options): Use quoted strings. + (rs6000_disable_incompatible_switches): Likewise. + * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Use quoted + strings, and make more translator-friendly. + (SUBSUBTARGET_OVERRIDE_OPTIONS): Use quoted strings. + +2017-08-14 Bin Cheng + + PR tree-optimization/81799 + * tree-loop-distribution.c (version_loop_by_alias_check): Force + cond_expr to simple gimple operand. + +2017-08-14 Wilco Dijkstra + + PR middle-end/46932 + * doc/sourcebuild.texi (autoincdec): Add autoincdec description. + +2017-08-14 Georg-Johann Lay + + PR target/81754 + PR target/81268 + * config/avr/avr.opt (mgas-isr-prologues): New Var avr_gasisr_prologues. + * config/avr/avr.md (gasisr, *gasisr): Use it instead of + TARGET_GASISR_PROLOGUES. + * config/avr/avr.c (avr_option_override): Same. + (avr_pass_pre_proep::execute): Same. + +2017-08-13 H.J. Lu + + PR target/81820 + * config/i386/i386.c (ix86_finalize_stack_frame_flags): Replace + frame pointer with stack pointer - UNITS_PER_WORD in debug insns. + +2017-08-13 Uros Bizjak + + * config/i386/i386.md (*load_tp_): Redefine as + define_insn_and_split. Split to a memory load from 0 in + DEFAULT_TLS_SEG_REG address space. Merge with *load_tp_x32 + using PTR mode iterator. + (*load_tp_x32_zext"): Redefine as define_insn_and_split. + Split to a memory load from 0 in DEFAULT_TLS_SEG_REG address space. + (*add_tp_): Redefine as define_insn_and_split. + Split to an add with a memory load from 0 in DEFAULT_TLS_SEG_REG + address space. Merge with *add_tp_x32 using PTR mode iterator. + (*add_tp_x32_zext"): Redefine as define_insn_and_split. + Split to an add with a memory load from 0 in + DEFAULT_TLS_SEG_REG address space. + +2017-08-12 Andrew Pinski + + * config/aarch64/aarch64-option-extensions.def (rdma): + Fix feature string to what Linux prints out in /proc/cpuinfo. + +2017-08-12 Pierre-Marie de Rodat + + PR ada/79542 + * dwarf2out.c (modified_type_die): For C typedef types that have + an ultimate origin, process the ultimate origin instead of the + input type. + (gen_typedef_die): Assert that input DECLs have no ultimate + origin. + (gen_type_die_with_usage): For typedef variants that have an + ultimate origin, just call gen_decl_die on the original DECL. + (process_scope_var): Avoid creating DIEs for local typedefs and + concrete static variables. + +2017-08-12 Alan Modra + + PR target/81170 + PR target/81295 + * config/rs6000/sysv4.h (STARTFILE_LINUX_SPEC): Upgrade to + match gnu-user.h startfile. + (ENDFILE_LINUX_SPEC): Similarly. + +2017-08-11 Thomas Schwinge + + PR lto/81430 + * config/nvptx/nvptx.c (nvptx_override_options_after_change): + Remove function. + (TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE): Remove definition. + +2017-08-11 Tamar Christina + * config/aarch64/aarch64.md (mov): Change. + (*movhf_aarch64, *movsf_aarch64, *movdf_aarch64): + aarch64_reg_or_fp_float into aarch64_reg_or_fp_zero. + * config/aarch64/predicates.md (aarch64_reg_or_fp_float): Removed. + +2017-08-11 Eric Botcazou + + * tree-sra.c (build_access_from_expr_1): Use more precise diagnostics + for storage order barriers. + +2017-08-11 Martin Liska + + PR tree-opt/79987 + * tree-chkp.c (chkp_get_bounds_for_decl_addr): Do not instrument + variables of void type. + +2017-08-11 Martin Liska + + * asan.c (asan_protect_global): Replace ASM_OUTPUT_DEF with + TARGET_SUPPORTS_ALIASES. + * cgraph.c (cgraph_node::create_same_body_alias): Likewise. + * ipa-visibility.c (can_replace_by_local_alias): Likewise. + (optimize_weakref): Likewise. + * symtab.c (symtab_node::noninterposable_alias): Likewise. + * varpool.c (varpool_node::create_extra_name_alias): Likewise. + * defaults.h: Introduce TARGET_SUPPORTS_ALIASES. + +2017-08-11 Martin Liska + + PR ipa/81213 + * config/i386/i386.c (make_resolver_func): Do complete + refactoring of the function. + +2017-08-10 Uros Bizjak + + PR target/81708 + * config/i386/i386.opt (mstack-protector-guard-symbol=): New option + * config/i386/i386.c (ix86_stack_protect_guard): Use + ix86_stack_protect_guard_symbol_str to generate varible declaration. + * doc/invoke.texi (x86 Options): Document + -mstack-protector-guard-symbol= option. + +2017-08-10 Uros Bizjak + + * config/i386/i386-protos.h (ix86_split_stack_guard): New prototype. + * config/i386/i386.c (ix86_split_stack_guard): New function. + (ix86_xpand_split_stack_prologue): Call ix86_split_stack_guard. + (ix86_legitimate_address_p) : Remove. + (i386_asm_output_addr_const_extra) : Ditto. + (optput_pic_addr_const): Remove UNSPEC_STACK_CHECK handling. + * config/i386/i386.md (unspec): Remove UNSPEC_STACK_CHECK. + (split_stack_space_check): Call ix86_split_stack_guard. + +2017-08-10 Martin Sebor + + * print-tree.c (print_node): Print location using the established + format %s:%i%i. + Replace spaces with colons. + (debug_raw, debug): Ditto. + +2017-08-10 Martin Sebor + + PR c++/81586 + * pretty-print.c (pp_format): Correct the handling of %s precision. + +2017-08-10 H.J. Lu + + PR target/81736 + * config/i386/i386.c (ix86_finalize_stack_realign_flags): Renamed + to ... + (ix86_finalize_stack_frame_flags): This. Also clear + frame_pointer_needed if -fno-omit-frame-pointer is used without + stack access. + (ix86_expand_prologue): Replace ix86_finalize_stack_realign_flags + with ix86_finalize_stack_frame_flags. + (ix86_expand_epilogue): Likewise. + (ix86_expand_split_stack_prologue): Likewise. + * doc/invoke.texi: Add a note for -fno-omit-frame-pointer. + +2017-08-10 Martin Liska + + PR c++/81355 + * c-attribs.c (handle_target_attribute): + Report warning for an empty string argument of target attribute. + +2017-08-09 Jakub Jelinek + + PR c/81687 + * omp-low.c (omp_copy_decl): Don't remap FORCED_LABEL or DECL_NONLOCAL + LABEL_DECLs. + * tree-cfg.c (move_stmt_op): Don't adjust DECL_CONTEXT of FORCED_LABEL + or DECL_NONLOCAL labels. + (move_stmt_r) : Adjust DECL_CONTEXT of FORCED_LABEL + or DECL_NONLOCAL labels here. + +2017-08-09 Will Schmidt + + * config/rs6000/rs6000.c (rs6000_option_override_internal): Add blurb + to indicate when early gimple folding has been disabled. + (rs6000_gimple_fold_builtin): Add debug content. + (rs6000_invalid_builtin): Fix whitespace. + (rs6000_expand_builtin): Fix whitespace. + * config/rs6000/rs6000.opt: Add option for -mfold-gimple. + +2017-08-09 Segher Boessenkool + + PR target/80938 + * config/rs6000/rs6000.c (rs6000_savres_strategy): Don't use + SAVE_MULTIPLE if not all the registers that saves, should be saved. + +2017-08-09 Jim Wilson + + * config/aarch64/aarch64-cores.def (falkor): Use falkor pipeline. + (qdf24xx): Likewise. + * config/aarch64/aarch64.md: Include falkor.md. + * config/aarch64/falkor.md: New. + +2017-08-09 Marek Polacek + + PR c/81233 + * diagnostic-core.h (emit_diagnostic_valist): Add declaration. + * diagnostic.c (emit_diagnostic): Add a comment. + (emit_diagnostic_valist): New function. + +2017-08-09 Marek Polacek + + PR c/81417 + * input.c (make_location): New overload. + * input.h (make_location): Declare. + +2017-08-08 Alan Modra + H.J. Lu + + PR driver/81523 + * gcc.c (NO_PIE_SPEC): Delete. + (PIE_SPEC): Define as !no-pie/pie. Move static|shared|r + exclusion.. + (LINK_PIE_SPEC): ..to here. + (LINK_COMMAND_SPEC): Support -no-pie. + * config/gnu-user.h (GNU_USER_TARGET_STARTFILE_SPEC): Correct + chain of crtbegin*.o selection, update for PIE_SPEC changes and + format. + (GNU_USER_TARGET_ENDFILE_SPEC): Similarly. + * config/sol2.h (STARTFILE_CRTBEGIN_SPEC): Similarly. + (ENDFILE_CRTEND_SPEC): Similarly. + +2017-08-08 Uros Bizjak + + PR target/81708 + * config/i386/i386.opt (mstack-protector-guard-reg=): New option + (mstack-protector-guard-offset=): Ditto. + * config/i386/i386.c (ix86_option_override): Handle + -mstack-protector-guard-reg= and -mstack-protector-guard-offset= + options. + (ix86_stack_protect_guard): Use ix86_stack_protect_guard_reg and + ix86_stack_protect_guard_offset variables. + (TARGET_STACK_PROTECT_GUARD): Always define. + * doc/invoke.texi (x86 Options): Document -mstack-protector-guard-reg= + and -mstack-protector-guard-offset= options. + +2017-08-08 Bin Cheng + + * tree-ssa-loop-ivopts.c (relate_compare_use_with_all_cands): Handle + boundary case for the last candidate. + +2017-08-08 Bin Cheng + + * doc/invoke.texi: Document -ftree-loop-distribution for O3. + * opts.c (default_options_table): Add OPT_ftree_loop_distribution. + +2017-08-08 Tamar Christina + + PR middle-end/19706 + * config/aarch64/aarch64.md (xorsign3): New optabs. + * config/aarch64/aarch64-builtins.c + (aarch64_builtin_vectorized_function): Added CASE_CFN_XORSIGN. + * config/aarch64/aarch64-simd-builtins.def: Added xorsign BINOP. + * config/aarch64/aarch64-simd.md: Added xorsign3 + +2017-08-08 Tamar Christina + Andrew Pinski + + PR middle-end/19706 + * internal-fn.def (XORSIGN): New. + * optabs.def (xorsign_optab): New. + * tree-ssa-math-opts.c (is_copysign_call_with_1): New. + (convert_expand_mult_copysign): New. + (pass_optimize_widening_mul::execute): Call + convert_expand_mult_copysign. + +2017-08-08 Bill Schmidt + + PR tree-optimization/81354 + * gimple-ssa-strength-reduction.c (create_add_on_incoming_edge): + Insert on edges rather than explicitly creating landing pads. + (analyze_candidates_and_replace): Commit edge inserts. + +2017-08-08 Richard Biener + + PR middle-end/81719 + * tree-ssa-loop-niter.c: Include tree-dfa.h. + (expand_simple_operations): Also look through ADDR_EXPRs with + MEM_REF bases treating them as POINTER_PLUS_EXPR. + +2017-08-08 Richard Biener + + PR tree-optimization/81723 + * tree-vect-slp.c (struct bst_traits): New hash traits. + (bst_fail): New global. + (vect_build_slp_tree_2): New worker, split out from ... + (vect_build_slp_tree): ... this now wrapping it with using + bst_fail set to cache SLP tree build fails. Properly handle + max_tree_size. + (vect_analyze_slp_instance): Allocate and free bst_fail. + +2017-08-08 Martin Liska + + PR tree-opt/81696 + * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Consider + LABEL_DECLs that can be from a different function. + +2017-08-08 Bin Cheng + + PR tree-optimization/81744 + * tree-predcom.c (prepare_finalizers_chain): Deep copy expr of + loop's number of iterations. + +2017-08-08 Martin Liska + + * asan.c: Include header files. + * attribs.c (build_decl_attribute_variant): New function moved + from tree.[ch]. + (build_type_attribute_qual_variant): Likewise. + (cmp_attrib_identifiers): Likewise. + (simple_cst_list_equal): Likewise. + (omp_declare_simd_clauses_equal): Likewise. + (attribute_value_equal): Likewise. + (comp_type_attributes): Likewise. + (build_type_attribute_variant): Likewise. + (lookup_ident_attribute): Likewise. + (remove_attribute): Likewise. + (merge_attributes): Likewise. + (merge_type_attributes): Likewise. + (merge_decl_attributes): Likewise. + (merge_dllimport_decl_attributes): Likewise. + (handle_dll_attribute): Likewise. + (attribute_list_equal): Likewise. + (attribute_list_contained): Likewise. + * attribs.h (lookup_attribute): New function moved from tree.[ch]. + (lookup_attribute_by_prefix): Likewise. + * bb-reorder.c: Include header files. + * builtins.c: Likewise. + * calls.c: Likewise. + * cfgexpand.c: Likewise. + * cgraph.c: Likewise. + * cgraphunit.c: Likewise. + * convert.c: Likewise. + * dwarf2out.c: Likewise. + * final.c: Likewise. + * fold-const.c: Likewise. + * function.c: Likewise. + * gimple-expr.c: Likewise. + * gimple-fold.c: Likewise. + * gimple-pretty-print.c: Likewise. + * gimple.c: Likewise. + * gimplify.c: Likewise. + * hsa-common.c: Likewise. + * hsa-gen.c: Likewise. + * internal-fn.c: Likewise. + * ipa-chkp.c: Likewise. + * ipa-cp.c: Likewise. + * ipa-devirt.c: Likewise. + * ipa-fnsummary.c: Likewise. + * ipa-inline.c: Likewise. + * ipa-visibility.c: Likewise. + * ipa.c: Likewise. + * lto-cgraph.c: Likewise. + * omp-expand.c: Likewise. + * omp-general.c: Likewise. + * omp-low.c: Likewise. + * omp-offload.c: Likewise. + * omp-simd-clone.c: Likewise. + * opts-global.c: Likewise. + * passes.c: Likewise. + * predict.c: Likewise. + * sancov.c: Likewise. + * sanopt.c: Likewise. + * symtab.c: Likewise. + * toplev.c: Likewise. + * trans-mem.c: Likewise. + * tree-chkp.c: Likewise. + * tree-eh.c: Likewise. + * tree-into-ssa.c: Likewise. + * tree-object-size.c: Likewise. + * tree-parloops.c: Likewise. + * tree-profile.c: Likewise. + * tree-ssa-ccp.c: Likewise. + * tree-ssa-live.c: Likewise. + * tree-ssa-loop.c: Likewise. + * tree-ssa-sccvn.c: Likewise. + * tree-ssa-structalias.c: Likewise. + * tree-ssa.c: Likewise. + * tree-streamer-in.c: Likewise. + * tree-vectorizer.c: Likewise. + * tree-vrp.c: Likewise. + * tsan.c: Likewise. + * ubsan.c: Likewise. + * varasm.c: Likewise. + * varpool.c: Likewise. + * tree.c: Remove functions moved to attribs.[ch]. + * tree.h: Likewise. + * config/aarch64/aarch64.c: Add attrs.h header file. + * config/alpha/alpha.c: Likewise. + * config/arc/arc.c: Likewise. + * config/arm/arm.c: Likewise. + * config/avr/avr.c: Likewise. + * config/bfin/bfin.c: Likewise. + * config/c6x/c6x.c: Likewise. + * config/cr16/cr16.c: Likewise. + * config/cris/cris.c: Likewise. + * config/darwin.c: Likewise. + * config/epiphany/epiphany.c: Likewise. + * config/fr30/fr30.c: Likewise. + * config/frv/frv.c: Likewise. + * config/ft32/ft32.c: Likewise. + * config/h8300/h8300.c: Likewise. + * config/i386/winnt.c: Likewise. + * config/ia64/ia64.c: Likewise. + * config/iq2000/iq2000.c: Likewise. + * config/lm32/lm32.c: Likewise. + * config/m32c/m32c.c: Likewise. + * config/m32r/m32r.c: Likewise. + * config/m68k/m68k.c: Likewise. + * config/mcore/mcore.c: Likewise. + * config/microblaze/microblaze.c: Likewise. + * config/mips/mips.c: Likewise. + * config/mmix/mmix.c: Likewise. + * config/mn10300/mn10300.c: Likewise. + * config/moxie/moxie.c: Likewise. + * config/msp430/msp430.c: Likewise. + * config/nds32/nds32-isr.c: Likewise. + * config/nds32/nds32.c: Likewise. + * config/nios2/nios2.c: Likewise. + * config/nvptx/nvptx.c: Likewise. + * config/pa/pa.c: Likewise. + * config/pdp11/pdp11.c: Likewise. + * config/powerpcspe/powerpcspe.c: Likewise. + * config/riscv/riscv.c: Likewise. + * config/rl78/rl78.c: Likewise. + * config/rx/rx.c: Likewise. + * config/s390/s390.c: Likewise. + * config/sh/sh.c: Likewise. + * config/sol2.c: Likewise. + * config/sparc/sparc.c: Likewise. + * config/spu/spu.c: Likewise. + * config/stormy16/stormy16.c: Likewise. + * config/tilegx/tilegx.c: Likewise. + * config/tilepro/tilepro.c: Likewise. + * config/v850/v850.c: Likewise. + * config/vax/vax.c: Likewise. + * config/visium/visium.c: Likewise. + * config/xtensa/xtensa.c: Likewise. + +2017-08-07 Michael Meissner + + PR target/81593 + * config/rs6000/vsx.md (vsx_concat_, VSX_D): Cleanup + constraints since the -mupper-regs-* switches have been + eliminated. + (vsx_concat__1): New combiner insns to recognize inserting + into a vector from a double word element that was extracted from + another vector, and eliminate extra XXPERMDI instructions. + (vsx_concat__2): Likewise. + (vsx_concat__3): Likewise. + (vsx_set_, VSX_D): Rewrite vector set in terms of vector + concat to allow optimizing inserts from previous extracts. + +2017-08-07 Uros Bizjak + + * config/i386/i386.c (ix86_stack_protect_guard): Generate + memory reference to a SSP offset in TLS address space. + (ix86_print_operand) : Remove. + (ix86_print_operand_punct_valid_p): Remove '@' code. + * config/i386/i386.md (unspec): Remove UNSPEC_SP_TLS_SET and + UNSPEC_SP_TLS_TEST. + (stack_tls_protect_set_): Remove. + (stack_protect_set): Do not call gen_stack_tls_protect_set_. + (stack_tls_protect_test_): Remove. + (stack_protect_test): Do not call gen_stack_tls_protect_test_. + +2017-08-07 Olivier Hainque + + PR target/81755 + * config/vxworksae.h (VXWORKS_HAVE_TLS): Define. + +2017-08-07 Douglas Rupp + + * Makefile.in (install-mkheaders): Fix typo, where the multi_dir + variable was referenced as multidir in command. + +2017-08-07 Jakub Jelinek + + PR c/69389 + * gimplify.c (goa_stabilize_expr): Handle BIT_INSERT_EXPR and + BIT_FIELD_REF. + +2017-08-07 Martin Liska + + * config/m32c/m32c.c: Add include of stringpool.h and attribs.h. + * config/rl78/rl78.c: Add include of attribs.h. + * config/sh/sh.c: Likewise. + * config/v850/v850.c: Likewise. + +2017-08-07 Tom de Vries + + PR middle-end/78266 + * omp-expand.c (expand_oacc_for): Ensure diff_type is large enough. + +2017-08-07 Martin Liska + + * config/mips/mips.c: Include attribs.h. + +2017-08-07 Thomas Koenig + + PR fortran/68829 + * doc/invoke.texi: Document change in behvaior for -Ofast for + Fortran. + +2017-08-07 Wilco Dijkstra + + * config/aarch64/aarch64.c (aarch64_pushwb_single_reg): + Use gen_frame_mem. + (aarch64_pop_regs): Likewise. + (aarch64_gen_load_pair): Likewise. + (aarch64_save_callee_saves): Likewise. + (aarch64_restore_callee_saves): Likewise. + +2017-08-07 H.J. Lu + + * config/i386/i386.c: Revert the last change. + +2017-08-07 H.J. Lu + + PR target/81736 + * config/i386/i386.c (ix86_finalize_stack_realign_flags): Renamed + to ... + (ix86_finalize_stack_frame_flags): This. Also clear + frame_pointer_needed if -fno-omit-frame-pointer is used without + stack access. + (ix86_expand_prologue): Replace ix86_finalize_stack_realign_flags + with ix86_finalize_stack_frame_flags. + (ix86_expand_epilogue): Likewise. + (ix86_expand_split_stack_prologue): Likewise. + +2017-08-07 H.J. Lu + + PR target/81743 + * config/i386/i386.c (get_builtin_code_for_version): Set priority + to P_AES for Westmere. + +2017-08-07 Jonathan Yong <10walls@gmail.com> + + * config/i386/mingw.opt (fset-stack-executable): Removed. + * config/i386/cygming.opt (fset-stack-executable): Moved + from mingw.opt. + * config/i386/cygwin.h: Define CHECK_EXECUTE_STACK_ENABLED. + +2017-08-07 Segher Boessenkool + + * print-rtl.c (print_exp): Print NOT as "~" instead of as "!". + +2017-08-07 Marek Polacek + + PR middle-end/81737 + * fold-const.c (fold_indirect_ref_1): Check type_domain. + +2017-08-07 Martin Liska + + * attribs.h (canonicalize_attr_name): New function. + (cmp_attribs): Move from c-format.c and adjusted. + (is_attribute_p): Moved from tree.h. + * tree-inline.c: Add new includes. + * tree.c (cmp_attrib_identifiers): Use cmp_attribs. + (private_is_attribute_p): Remove. + (private_lookup_attribute): Likewise. + (private_lookup_attribute_by_prefix): Simplify. + (remove_attribute): Use is_attribute_p. + * tree.h: Remove removed declarations. + +2017-08-07 Jakub Jelinek + + PR middle-end/81698 + * stmt.c (emit_case_dispatch_table): Add DEFAULT_EDGE argument, + instead of computing it in the function. Formatting fix. + (expand_case): Don't rely on default_edge being the first edge, + clear it if removing it, pass default_edge to + emit_case_dispatch_table. + (expand_sjlj_dispatch_table): Pass NULL as DEFAULT_EDGE, formatting + fix. + +2017-08-06 Uros Bizjak + + * config/alpha/alpha.c (alpha_reorg): If trap is the last active + insn in the function, emit NOP after the insn. + +2017-08-06 Tom de Vries + + * omp-expand.c (expand_oacc_for): Add missing edge probability for tile + and element loops. + +2017-08-06 Tom de Vries + + * omp-expand.c (expand_oacc_for): Add missing edge probability for chunk + loop. + +2017-08-04 Yury Gribov + + PR tree-optimization/57371 + * match.pd: New pattern. + +2017-08-04 Marek Polacek + + PR middle-end/81695 + * fold-const.c (fold_indirect_ref_1): For ((int *)&a + 4 -> a[1], + perform the computation in offset_int. + +2017-08-04 Richard Sandiford + + PR tree-optimization/81136 + * tree-vectorizer.h: Include tree-hash-traits.h. + (vec_base_alignments): New typedef. + (vec_info): Add a base_alignments field. + (vect_record_base_alignments): Declare. + * tree-data-ref.h (data_reference): Add an is_conditional_in_stmt + field. + (DR_IS_CONDITIONAL_IN_STMT): New macro. + (create_data_ref): Add an is_conditional_in_stmt argument. + * tree-data-ref.c (create_data_ref): Likewise. Use it to initialize + the is_conditional_in_stmt field. + (data_ref_loc): Add an is_conditional_in_stmt field. + (get_references_in_stmt): Set the is_conditional_in_stmt field. + (find_data_references_in_stmt): Update call to create_data_ref. + (graphite_find_data_references_in_stmt): Likewise. + * tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Likewise. + * tree-vect-data-refs.c (vect_analyze_data_refs): Likewise. + (vect_record_base_alignment): New function. + (vect_record_base_alignments): Likewise. + (vect_compute_data_ref_alignment): Adjust base_addr and aligned_to + for nested statements even if we fail to compute a misalignment. + Use pooled base alignments for unconditional references. + (vect_find_same_alignment_drs): Compare base addresses instead + of base objects. + (vect_analyze_data_refs_alignment): Call vect_record_base_alignments. + * tree-vect-slp.c (vect_slp_analyze_bb_1): Likewise. + +2017-08-04 Richard Sandiford + + * tree-vectorizer.h (vec_info): Add a constructor and destructor. + Add an explicit name for the enum. Use auto_vec for slp_instances + and grouped_stores. + (_loop_vec_info): Add a constructor and destructor. Use auto_vec + for all vectors. + (_bb_vec_info): Add a constructor and destructor. + (vinfo_for_stmt): Return NULL for uids of -1 as well. + (destroy_loop_vec_info): Delete. + (vect_destroy_datarefs): Likewise. + * tree-vectorizer.c (vect_destroy_datarefs): Delete. + (vec_info::vec_info): New function. + (vec_info::~vec_info): Likewise. + (vectorize_loops): Use delete instead of destroy_loop_vec_info. + * tree-parloops.c (gather_scalar_reductions): Use delete instead of + destroy_loop_vec_info. + * tree-vect-loop.c (new_loop_vec_info): Replace with... + (_loop_vec_info::_loop_vec_info): ...this. + (destroy_loop_vec_info): Replace with... + (_loop_vec_info::~_loop_vec_info): ...this. Unconditionally delete + the stmt_vec_infos. Leave handling of vec_info information to its + destructor. Remove explicit vector releases. + (vect_analyze_loop_form): Use new instead of new_loop_vec_info. + (vect_analyze_loop): Use delete instead of destroy_loop_vec_info. + * tree-vect-slp.c (new_bb_vec_info): Replace with... + (_bb_vec_info::_bb_vec_info): ...this. Don't reserve space in + BB_VINFO_GROUPED_STORES or BB_VINFO_SLP_INSTANCES. + (destroy_bb_vec_info): Replace with... + (_bb_vec_info::~_bb_vec_info): ...this. Leave handling of vec_info + information to its destructor. + (vect_slp_analyze_bb_1): Use new and delete instead of + new_bb_vec_info and destroy_bb_vec_info. + (vect_slp_bb): Replace 2 calls to destroy_bb_vec_info with a + single delete. + +2017-08-04 Richard Sandiford + + * tree-data-ref.h (subscript): Add access_fn field. + (data_dependence_relation): Add could_be_independent_p. + (SUB_ACCESS_FN, DDR_COULD_BE_INDEPENDENT_P): New macros. + (same_access_functions): Move to tree-data-ref.c. + * tree-data-ref.c (ref_contains_union_access_p): New function. + (access_fn_component_p): Likewise. + (access_fn_components_comparable_p): Likewise. + (dr_analyze_indices): Add a reference to access_fn_component_p. + (dump_data_dependence_relation): Use SUB_ACCESS_FN instead of + DR_ACCESS_FN. + (constant_access_functions): Likewise. + (add_other_self_distances): Likewise. + (same_access_functions): Likewise. (Moved from tree-data-ref.h.) + (initialize_data_dependence_relation): Use XCNEW and remove + explicit zeroing of DDR_REVERSED_P. Look for a subsequence + of access functions that have the same type. Allow the + subsequence to end with different bases in some circumstances. + Record the chosen access functions in SUB_ACCESS_FN. + (build_classic_dist_vector_1): Replace ddr_a and ddr_b with + a_index and b_index. Use SUB_ACCESS_FN instead of DR_ACCESS_FN. + (subscript_dependence_tester_1): Likewise dra and drb. + (build_classic_dist_vector): Update calls accordingly. + (subscript_dependence_tester): Likewise. + * tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Check + DDR_COULD_BE_INDEPENDENT_P. + * tree-vectorizer.h (LOOP_REQUIRES_VERSIONING_FOR_ALIAS): Test + comp_alias_ddrs instead of may_alias_ddrs. + * tree-vect-data-refs.c (vect_analyze_possibly_independent_ddr): + New function. + (vect_analyze_data_ref_dependence): Use it if + DDR_COULD_BE_INDEPENDENT_P, but fall back to using the recorded + distance vectors if that fails. + (dependence_distance_ge_vf): New function. + (vect_prune_runtime_alias_test_list): Use it. Don't clear + LOOP_VINFO_MAY_ALIAS_DDRS. + +2017-08-04 Richard Biener + + PR middle-end/81705 + * fold-const.c (fold_binary_loc): Properly restrict + minus_var0 && minus_var1 case when associating undefined overflow + entities. + +2017-08-04 Tom de Vries + + * omp-simd-clone.c (simd_clone_adjust): Add missing edge probability. + +2017-08-03 Bill Schmidt + + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): + Don't start diagnostic messages with a capital letter. + * config/rs6000/rs6000.c (rs6000_option_override_internal): + Likewise. + (rs6000_invalid_builtin): Likewise. + (rs6000_trampoline_init): Likewise. + +2017-08-03 Jakub Jelinek + + PR target/81621 + * bb-reorder.c (pass_partition_blocks::execute): Return TODO_df_finish + after setting changeable df flags. + +2017-08-03 Richard Biener + + * tree-ssa-reassoc.c (should_break_up_subtract): Also break + up if the use is in USE - X. + +2017-08-03 Alexander Monakov + + * toplev.c (dumpfile.h): New include. + (internal_error_reentered): New static function. Use it... + (internal_error_function): ...here to handle reentered internal_error. + +2017-08-03 Richard Biener + + PR middle-end/81148 + * fold-const.c (split_tree): Add minus_var and minus_con + arguments, remove unused loc arg. Never generate NEGATE_EXPRs + here but always use minus_*. + (associate_trees): Assert we never associate with MINUS_EXPR + and NULL first operand. Do not recurse for PLUS_EXPR operands + when associating as MINUS_EXPR either. + (fold_binary_loc): Track minus_var and minus_con. + +2017-08-03 Tom de Vries + + PR lto/81430 + * tree-streamer-in.c (lto_input_ts_function_decl_tree_pointers): If + ACCEL_COMPILER, apply finish_options on + DECL_FUNCTION_SPECIFIC_OPTIMIZATION. + +2017-08-03 Tom de Vries + + PR target/81662 + * config/nvptx/nvptx.c (nvptx_option_override): Emit sorry if + function_entry_patch_area_size > 0. + +2017-08-03 Jakub Jelinek + + PR driver/81650 + * calls.c (alloc_max_size): Use HOST_WIDE_INT_UC (10??) + instead of 10??LU, perform unit multiplication in wide_int, + don't change alloc_object_size_limit if the limit is larger + than SSIZE_MAX. + + PR tree-optimization/81655 + PR tree-optimization/81588 + * tree-ssa-reassoc.c (optimize_range_tests_var_bound): Handle also + the case when ranges[i].low and high are 1 for unsigned type with + precision 1. + + PR middle-end/81052 + * omp-low.c (diagnose_sb_0): Handle flag_openmp_simd like flag_openmp. + (pass_diagnose_omp_blocks::gate): Enable also for flag_openmp_simd. + +2017-08-03 Prathamesh Kulkarni + + * tree-vrp.h: Add include guard. + +2017-08-02 Uros Bizjak + + PR target/81644 + * config/i386/i386.md (unspecv): Add UNSPECV_UD2. + (ud2): New insn pattern. + * config/i386/i386.c (ix86_expand_epilogue): + For naked functions, generate ud2 instead of trap insn. + +2017-08-02 Marek Polacek + + PR other/81667 + * alloc-pool.h (base_pool_allocator): Initialize m_elt_size. + +2017-08-02 Tom de Vries + Cesar Philippidis + + * config/nvptx/nvptx.c (nvptx_lockless_update, nvptx_lockfull_update): + Add missing edge probabilities. + +2017-08-02 Tamar Christina + + * config/aarch64/aarch64.c (aarch64_reinterpret_float_as_int): + Correct endianness. + +2017-08-02 Jakub Jelinek + + PR middle-end/79499 + * function.c (thread_prologue_and_epilogue_insns): Determine blocks + for find_many_sub_basic_blocks bitmap by looking up BLOCK_FOR_INSN + of first NONDEBUG_INSN_P in each of the split_prologue_seq and + prologue_seq sequences - if any. + +2017-08-02 Richard Biener + + * tree-vect-stmts.c (vectorizable_store): Perform vector extracts + via vectors if supported, integer extracts via punning if supported + or otherwise vector extracts. + +2017-08-02 Richard Biener + + * tree-ssa-pre.c (bitmap_insert_into_set_1): Remove and inline + into ... + (bitmap_insert_into_set): ... this. + +2017-08-02 Richard Biener + + PR tree-optimization/81633 + Revert + 2015-08-17 Alan Hayward + + PR tree-optimization/71752 + * tree-vect-slp.c (vect_get_slp_defs): Handle null operands. + +2017-08-01 Daniel Santos + + * config/i386/i386.h (ix86_frame::outlined_save_offset): Remove field. + (machine_function::call_ms2sysv_pad_out): Remove field. + * config/i386/i386.c (xlogue_layout::get_stack_space_used): Modify. + (ix86_compute_frame_layout): Likewise. + +2017-08-01 H.J. Lu + + PR target/81654 + * config/i386/i386.c (ix86_set_func_type): Disallow naked + attribute with interrupt attribute. + +2017-08-01 Andrew Pinski + + * tree-ssa-scopedtables.c (hashable_expr_equal_p): Check + BIT_INSERT_EXPR's operand 1 + to see if the types precision matches. + +2017-08-01 Martin Liska + + PR middle-end/70140 + * builtins.c (expand_builtin_memcpy_args): Remove. + (expand_builtin_memcpy): Call newly added function + expand_builtin_memory_copy_args. + (expand_builtin_memcpy_with_bounds): Likewise. + (expand_builtin_mempcpy): Remove last argument. + (expand_builtin_mempcpy_with_bounds): Likewise. + (expand_builtin_memory_copy_args): New function created from + expand_builtin_mempcpy_args with small modifications. + (expand_builtin_mempcpy_args): Remove. + (expand_builtin_stpcpy): Remove unused argument. + (expand_builtin): Likewise. + (expand_builtin_with_bounds): Likewise. + +2017-08-01 Martin Liska + + Revert r250771 + Make mempcpy more optimal (PR middle-end/70140). + +2017-08-01 Jakub Jelinek + + PR target/81622 + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): For + __builtin_vec_cmpne verify both arguments are compatible vectors + before looking at TYPE_MODE on the element type. For __builtin_vec_ld + verify arg1_type is a pointer or array type. For __builtin_vec_st, + move computation of aligned to after checking the argument types. + Formatting fixes. + + PR target/80846 + * config/rs6000/vsx.md (vextract_fp_from_shorth, + vextract_fp_from_shortl): Add element mode after mode in gen_vec_init* + calls. + +2017-08-01 Jerome Lambourg + Doug Rupp + Olivier Hainque + + * config.gcc (arm-wrs-vxworks*): Rework to handle arm-wrs-vxworks7 as + well as arm-wrs-vxworks. Update target_cpu_name from arm6 (arch v3) to + arm8 (arch v4). + * config/arm/vxworks.h (MAYBE_TARGET_BPABI_CPP_BUILTINS): New, helper + for TARGET_OS_CPP_BUILTIN. + (TARGET_OS_CPP_BUILTIN): Invoke MAYBE_TARGET_BPABI_CPP_BUILTINS(), + refine CPU definitions for arm_arch5 and add those for arm_arch6 and + arm_arch7. + (MAYBE_ASM_ABI_SPEC): New, helper for SUBTARGET_EXTRA_ASM_SPEC, + passing required abi options to the assembler for EABI configurations. + (EXTRA_CC1_SPEC): New macro, to help prevent the implicit production + of .text.hot and .text.unlikely sections for kernel modules when + using ARM style exceptions. + (CC1_SPEC): Remove obsolete attempt at mimicking Diab toolchain + options. Add EXTRA_CC1_SPEC. + (VXWORKS_ENDIAN_SPEC): Adjust comment and remove handling of Diab + toolchain options. + (DWARF2_UNWIND_INFO): Redefine to handle the pre/post VxWorks 7 + transition. + (ARM_TARGET2_DWARF_FORMAT): Define. + * config/arm/t-vxworks: Adjust multilib control to removal of the + Diab command line options. + +2017-08-01 Martin Liska + + PR gcov-profile/81561 + * gcov.c (unblock): Make unblocking safe as we need to preserve + index correspondence of blocks and block_lists. + +2017-08-01 Richard Biener + + PR tree-optimization/81181 + * tree-ssa-pre.c (compute_antic_aux): Defer clean() to ... + (compute_antic): ... end of iteration here. + +2017-08-01 James Greenhalgh + + * common.opt (ftree-vectorize): No longer set flag_tree_vectorize. + (ftree-loop-vectorize): Set as EnabledBy ftree-vectorize. + (ftree-slp-vectorize): Likewise. + * omp-expand (expand_omp_simd): Remove flag_tree_vectorize, as it + can no longer be set independent of flag_tree_loop_vectorize. + * omp-general.c (emp_max_vf): Likewise. + * opts.c (enable_fdo_optimizations): Remove references to + flag_tree_vectorize, these are now implicit. + (common_handle_option): Remove handling for OPT_ftree_vectorize, + and leave it for the options machinery. + +2017-08-01 Martin Liska + + PR middle-end/70140 + * builtins.c (expand_builtin_memcpy_args): Remove. + (expand_builtin_memcpy): Call newly added function + expand_builtin_memory_copy_args. + (expand_builtin_memcpy_with_bounds): Likewise. + (expand_builtin_mempcpy): Remove last argument. + (expand_builtin_mempcpy_with_bounds): Likewise. + (expand_builtin_memory_copy_args): New function created from + expand_builtin_mempcpy_args with small modifications. + (expand_builtin_mempcpy_args): Remove. + (expand_builtin_stpcpy): Remove unused argument. + (expand_builtin): Likewise. + (expand_builtin_with_bounds): Likewise. + +2017-08-01 Uros Bizjak + + PR target/81641 + * config/i386/i386.c (ix86_print_operand_address_as): For -masm=intel + print "ds:" only for immediates in generic address space. + +2017-08-01 Uros Bizjak + + PR target/81639 + * config/i386/i386.c (ix86_funciton_naked): New prototype. + (ix86_function_ok_for_sibcall): Return false for naked functions. + +2017-08-01 Richard Biener + + * tree-ssa-pre.c (print_pre_expr): Handle NULL expr. + (compute_antic): Seed worklist with exit block predecessors. + * cfganal.c (dfs_find_deadend): For a cycle return the source + of the edge closing it. + +2017-08-01 Tamar Christina + + * config/aarch64/aarch64.c + (aarch64_can_const_movi_rtx_p): Move 0 check. + +2017-08-01 Bin Cheng + + * tree.h (POINTER_TYPE_OVERFLOW_UNDEFINED): Delete. + * fold-const.c (fold_comparison, fold_binary_loc): Delete use of + above macro. + * match.pd: Ditto in address comparison pattern. + +2017-08-01 Bin Cheng + + PR tree-optimization/81627 + * tree-predcom.c (prepare_finalizers): Always rewrite into loop + closed ssa form for store-store chain. + +2017-08-01 Bin Cheng + + PR tree-optimization/81620 + * tree-predcom.c (add_ref_to_chain): Don't set has_max_use_after + for store-store chain. + +2017-08-01 Jakub Jelinek + + PR tree-optimization/81588 + * tree-ssa-reassoc.c (optimize_range_tests_var_bound): If + ranges[i].in_p, invert comparison code ccode. For >/>=, + swap rhs1 and rhs2 and comparison code unconditionally, + for rank is BIT_IOR_EXPR. + + PR target/80846 + * optabs.def (vec_extract_optab, vec_init_optab): Change from + a direct optab to conversion optab. + * optabs.c (expand_vector_broadcast): Use convert_optab_handler + with GET_MODE_INNER as last argument instead of optab_handler. + * expmed.c (extract_bit_field_1): Likewise. Use vector from + vector extraction if possible and optab is available. + * expr.c (store_constructor): Use convert_optab_handler instead + of optab_handler. Use vector initialization from smaller + vectors if possible and optab is available. + * tree-vect-stmts.c (vectorizable_load): Likewise. + * doc/md.texi (vec_extract, vec_init): Document that the optabs + now have two modes. + * config/i386/i386.c (ix86_expand_vector_init): Handle expansion + of vec_init from half-sized vectors with the same element mode. + * config/i386/sse.md (ssehalfvecmode): Add V4TI case. + (ssehalfvecmodelower, ssescalarmodelower): New mode attributes. + (reduc_plus_scal_v8df, reduc_plus_scal_v4df, reduc_plus_scal_v2df, + reduc_plus_scal_v16sf, reduc_plus_scal_v8sf, reduc_plus_scal_v4sf, + reduc__scal_, reduc_umin_scal_v8hi): Add element mode + after mode in gen_vec_extract* calls. + (vec_extract): Renamed to ... + (vec_extract): ... this. + (vec_extract): New expander. + (rotl3, rotr3, 3, ashrv2di3): Add + element mode after mode in gen_vec_init* calls. + (VEC_INIT_HALF_MODE): New mode iterator. + (vec_init): Renamed to ... + (vec_init): ... this. + (vec_init): New expander. + * config/i386/mmx.md (vec_extractv2sf): Renamed to ... + (vec_extractv2sfsf): ... this. + (vec_initv2sf): Renamed to ... + (vec_initv2sfsf): ... this. + (vec_extractv2si): Renamed to ... + (vec_extractv2sisi): ... this. + (vec_initv2si): Renamed to ... + (vec_initv2sisi): ... this. + (vec_extractv4hi): Renamed to ... + (vec_extractv4hihi): ... this. + (vec_initv4hi): Renamed to ... + (vec_initv4hihi): ... this. + (vec_extractv8qi): Renamed to ... + (vec_extractv8qiqi): ... this. + (vec_initv8qi): Renamed to ... + (vec_initv8qiqi): ... this. + * config/rs6000/vector.md (VEC_base_l): New mode attribute. + (vec_init): Renamed to ... + (vec_init): ... this. + (vec_extract): Renamed to ... + (vec_extract): ... this. + * config/rs6000/paired.md (vec_initv2sf): Renamed to ... + (vec_initv2sfsf): ... this. + * config/rs6000/altivec.md (splitter, altivec_copysign_v4sf3, + vec_unpacku_hi_v16qi, vec_unpacku_hi_v8hi, vec_unpacku_lo_v16qi, + vec_unpacku_lo_v8hi, mulv16qi3, altivec_vreve2): Add + element mode after mode in gen_vec_init* calls. + * config/aarch64/aarch64-simd.md (vec_init): Renamed to ... + (vec_init): ... this. + (vec_extract): Renamed to ... + (vec_extract): ... this. + * config/aarch64/iterators.md (Vel): New mode attribute. + * config/s390/s390.c (s390_expand_vec_strlen, s390_expand_vec_movstr): + Add element mode after mode in gen_vec_extract* calls. + * config/s390/vector.md (non_vec_l): New mode attribute. + (vec_extract): Renamed to ... + (vec_extract): ... this. + (vec_init): Renamed to ... + (vec_init): ... this. + * config/s390/s390-builtins.def (s390_vlgvb, s390_vlgvh, s390_vlgvf, + s390_vlgvf_flt, s390_vlgvg, s390_vlgvg_dbl): Add element mode after + vec_extract mode. + * config/arm/iterators.md (V_elem_l): New mode attribute. + * config/arm/neon.md (vec_extract): Renamed to ... + (vec_extract): ... this. + (vec_extractv2di): Renamed to ... + (vec_extractv2didi): ... this. + (vec_init): Renamed to ... + (vec_init): ... this. + (reduc_plus_scal_, reduc_plus_scal_v2di, reduc_smin_scal_, + reduc_smax_scal_, reduc_umin_scal_, + reduc_umax_scal_, neon_vget_lane, neon_vget_laneu): + Add element mode after gen_vec_extract* calls. + * config/mips/mips-msa.md (vec_init): Renamed to ... + (vec_init): ... this. + (vec_extract): Renamed to ... + (vec_extract): ... this. + * config/mips/loongson.md (vec_init): Renamed to ... + (vec_init): ... this. + * config/mips/mips-ps-3d.md (vec_initv2sf): Renamed to ... + (vec_initv2sfsf): ... this. + (vec_extractv2sf): Renamed to ... + (vec_extractv2sfsf): ... this. + (reduc_plus_scal_v2sf, reduc_smin_scal_v2sf, reduc_smax_scal_v2sf): + Add element mode after gen_vec_extract* calls. + * config/mips/mips.md (unitmode): New mode iterator. + * config/spu/spu.c (spu_expand_prologue, spu_allocate_stack, + spu_builtin_extract): Add element mode after gen_vec_extract* calls. + * config/spu/spu.md (inner_l): New mode attribute. + (vec_init): Renamed to ... + (vec_init): ... this. + (vec_extract): Renamed to ... + (vec_extract): ... this. + * config/sparc/sparc.md (veltmode): New mode iterator. + (vec_init): Renamed to ... + (vec_init): ... this. + * config/ia64/vect.md (vec_initv2si): Renamed to ... + (vec_initv2sisi): ... this. + (vec_initv2sf): Renamed to ... + (vec_initv2sfsf): ... this. + (vec_extractv2sf): Renamed to ... + (vec_extractv2sfsf): ... this. + * config/powerpcspe/vector.md (VEC_base_l): New mode attribute. + (vec_init): Renamed to ... + (vec_init): ... this. + (vec_extract): Renamed to ... + (vec_extract): ... this. + * config/powerpcspe/paired.md (vec_initv2sf): Renamed to ... + (vec_initv2sfsf): ... this. + * config/powerpcspe/altivec.md (splitter, altivec_copysign_v4sf3, + vec_unpacku_hi_v16qi, vec_unpacku_hi_v8hi, vec_unpacku_lo_v16qi, + vec_unpacku_lo_v8hi, mulv16qi3): Add element mode after mode in + gen_vec_init* calls. + +2017-08-01 Richard Biener + + PR tree-optimization/81297 + * tree-vrp.c (get_single_symbol): Remove assert, instead drop + TREE_OVERFLOW from INTEGER_CSTs. + 2017-07-31 Segher Boessenkool * config/rs6000/rs6000.c (enum rs6000_reg_type): Delete trailing comma. @@ -16,14 +2278,16 @@ vector double vec_xl_be (signed long long, double *); vector float vec_xl_be (signed long long, float *); * config/rs6000/altivec.h (vec_xl_be): Add #define. - * config/rs6000/rs6000-builtin.def (XL_BE_V16QI, XL_BE_V8HI, XL_BE_V4SI, - XL_BE_V2DI, XL_BE_V4SF, XL_BE_V2DF, XL_BE): Add definitions for the builtins. + * config/rs6000/rs6000-builtin.def (XL_BE_V16QI, XL_BE_V8HI, XL_BE_V4SI) + XL_BE_V2DI, XL_BE_V4SF, XL_BE_V2DF, XL_BE): Add definitions + for the builtins. * config/rs6000/rs6000.c (altivec_expand_xl_be_builtin): Add function. - (altivec_expand_builtin): Add switch statement to call altivec_expand_xl_be - for each builtin. + (altivec_expand_builtin): Add switch statement to call + altivec_expand_xl_be for each builtin. (altivec_init_builtins): Add def_builtin for _builtin_vsx_le_be_v8hi, - __builtin_vsx_le_be_v4si, __builtin_vsx_le_be_v2di, __builtin_vsx_le_be_v4sf, - __builtin_vsx_le_be_v2df, __builtin_vsx_le_be_v16qi. + __builtin_vsx_le_be_v4si, __builtin_vsx_le_be_v2di, + __builtin_vsx_le_be_v4sf, __builtin_vsx_le_be_v2df, + __builtin_vsx_le_be_v16qi. * doc/extend.texi: Update the built-in documentation file for the new built-in functions. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cbcfeb9851863..54930fc057741 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20170731 +20170829 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index efca9169671a9..0bde7acf91415 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3776,7 +3776,7 @@ install-mkheaders: stmp-int-hdrs install-itoolsdirs \ set -e; for ml in `cat fixinc_list`; do \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}; \ - $(INSTALL_DATA) include-fixed$${multidir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ + $(INSTALL_DATA) include-fixed$${multi_dir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ done $(INSTALL_SCRIPT) $(srcdir)/../mkinstalldirs \ $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index dda51d423b633..87091b1c7f5ae 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2017-08-29 Martin Liska + + PR other/39851 + * gcc-interface/trans.c (Pragma_to_gnu): Set argument to NULL. + +2017-08-08 Martin Liska + + * gcc-interface/trans.c: Include header files. + 2017-07-29 Jakub Jelinek * gcc-interface/utils.c (gnat_write_global_declarations): Pass false diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 7844bd7c5a8c6..c0c6fb3091530 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -46,6 +46,8 @@ #include "gimplify.h" #include "opts.h" #include "common/common-target.h" +#include "stringpool.h" +#include "attribs.h" #include "ada.h" #include "adadecode.h" @@ -1484,7 +1486,7 @@ Pragma_to_gnu (Node_Id gnat_node) else option_index = 0; - set_default_handlers (&handlers); + set_default_handlers (&handlers, NULL); control_warning_option (option_index, (int) kind, arg, imply, location, lang_mask, &handlers, &global_options, &global_options_set, global_dc); diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h index a5236db3dae4b..1d04e5d2cfe91 100644 --- a/gcc/alloc-pool.h +++ b/gcc/alloc-pool.h @@ -240,8 +240,9 @@ base_pool_allocator ::base_pool_allocator ( const char *name, size_t size MEM_STAT_DECL): m_name (name), m_id (0), m_elts_per_block (0), m_returned_free_list (NULL), m_virgin_free_list (NULL), m_virgin_elts_remaining (0), m_elts_allocated (0), - m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL), m_size (size), - m_initialized (false), m_location (ALLOC_POOL_ORIGIN, false PASS_MEM_STAT) {} + m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL), m_elt_size (0), + m_size (size), m_initialized (false), + m_location (ALLOC_POOL_ORIGIN, false PASS_MEM_STAT) {} /* Initialize a pool allocator. */ diff --git a/gcc/asan.c b/gcc/asan.c index 5f9275f6425a1..ce1e0244ec687 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -47,6 +47,8 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "stor-layout.h" #include "tree-iterator.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" #include "dojump.h" #include "explow.h" @@ -1663,10 +1665,8 @@ asan_protect_global (tree decl) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) return false; -#ifndef ASM_OUTPUT_DEF - if (asan_needs_local_alias (decl)) + if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl)) return false; -#endif return true; } diff --git a/gcc/attribs.c b/gcc/attribs.c index 05fa8ef869286..faa0649e190d6 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -942,3 +942,636 @@ is_function_default_version (const tree decl) return (TREE_CODE (attr) == STRING_CST && strcmp (TREE_STRING_POINTER (attr), "default") == 0); } + +/* Return a declaration like DDECL except that its DECL_ATTRIBUTES + is ATTRIBUTE. */ + +tree +build_decl_attribute_variant (tree ddecl, tree attribute) +{ + DECL_ATTRIBUTES (ddecl) = attribute; + return ddecl; +} + +/* Return a type like TTYPE except that its TYPE_ATTRIBUTE + is ATTRIBUTE and its qualifiers are QUALS. + + Record such modified types already made so we don't make duplicates. */ + +tree +build_type_attribute_qual_variant (tree ttype, tree attribute, int quals) +{ + if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute)) + { + tree ntype; + + /* Building a distinct copy of a tagged type is inappropriate; it + causes breakage in code that expects there to be a one-to-one + relationship between a struct and its fields. + build_duplicate_type is another solution (as used in + handle_transparent_union_attribute), but that doesn't play well + with the stronger C++ type identity model. */ + if (TREE_CODE (ttype) == RECORD_TYPE + || TREE_CODE (ttype) == UNION_TYPE + || TREE_CODE (ttype) == QUAL_UNION_TYPE + || TREE_CODE (ttype) == ENUMERAL_TYPE) + { + warning (OPT_Wattributes, + "ignoring attributes applied to %qT after definition", + TYPE_MAIN_VARIANT (ttype)); + return build_qualified_type (ttype, quals); + } + + ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED); + ntype = build_distinct_type_copy (ttype); + + TYPE_ATTRIBUTES (ntype) = attribute; + + hashval_t hash = type_hash_canon_hash (ntype); + ntype = type_hash_canon (hash, ntype); + + /* If the target-dependent attributes make NTYPE different from + its canonical type, we will need to use structural equality + checks for this type. */ + if (TYPE_STRUCTURAL_EQUALITY_P (ttype) + || !comp_type_attributes (ntype, ttype)) + SET_TYPE_STRUCTURAL_EQUALITY (ntype); + else if (TYPE_CANONICAL (ntype) == ntype) + TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype); + + ttype = build_qualified_type (ntype, quals); + } + else if (TYPE_QUALS (ttype) != quals) + ttype = build_qualified_type (ttype, quals); + + return ttype; +} + +/* Compare two identifier nodes representing attributes. + Return true if they are the same, false otherwise. */ + +static bool +cmp_attrib_identifiers (const_tree attr1, const_tree attr2) +{ + /* Make sure we're dealing with IDENTIFIER_NODEs. */ + gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE + && TREE_CODE (attr2) == IDENTIFIER_NODE); + + /* Identifiers can be compared directly for equality. */ + if (attr1 == attr2) + return true; + + return cmp_attribs (IDENTIFIER_POINTER (attr1), IDENTIFIER_LENGTH (attr1), + IDENTIFIER_POINTER (attr2), IDENTIFIER_LENGTH (attr2)); +} + +/* Compare two constructor-element-type constants. Return 1 if the lists + are known to be equal; otherwise return 0. */ + +static bool +simple_cst_list_equal (const_tree l1, const_tree l2) +{ + while (l1 != NULL_TREE && l2 != NULL_TREE) + { + if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1) + return false; + + l1 = TREE_CHAIN (l1); + l2 = TREE_CHAIN (l2); + } + + return l1 == l2; +} + +/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are + the same. */ + +static bool +omp_declare_simd_clauses_equal (tree clauses1, tree clauses2) +{ + tree cl1, cl2; + for (cl1 = clauses1, cl2 = clauses2; + cl1 && cl2; + cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2)) + { + if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2)) + return false; + if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN) + { + if (simple_cst_equal (OMP_CLAUSE_DECL (cl1), + OMP_CLAUSE_DECL (cl2)) != 1) + return false; + } + switch (OMP_CLAUSE_CODE (cl1)) + { + case OMP_CLAUSE_ALIGNED: + if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1), + OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1) + return false; + break; + case OMP_CLAUSE_LINEAR: + if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1), + OMP_CLAUSE_LINEAR_STEP (cl2)) != 1) + return false; + break; + case OMP_CLAUSE_SIMDLEN: + if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1), + OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1) + return false; + default: + break; + } + } + return true; +} + + +/* Compare two attributes for their value identity. Return true if the + attribute values are known to be equal; otherwise return false. */ + +bool +attribute_value_equal (const_tree attr1, const_tree attr2) +{ + if (TREE_VALUE (attr1) == TREE_VALUE (attr2)) + return true; + + if (TREE_VALUE (attr1) != NULL_TREE + && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST + && TREE_VALUE (attr2) != NULL_TREE + && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST) + { + /* Handle attribute format. */ + if (is_attribute_p ("format", get_attribute_name (attr1))) + { + attr1 = TREE_VALUE (attr1); + attr2 = TREE_VALUE (attr2); + /* Compare the archetypes (printf/scanf/strftime/...). */ + if (!cmp_attrib_identifiers (TREE_VALUE (attr1), TREE_VALUE (attr2))) + return false; + /* Archetypes are the same. Compare the rest. */ + return (simple_cst_list_equal (TREE_CHAIN (attr1), + TREE_CHAIN (attr2)) == 1); + } + return (simple_cst_list_equal (TREE_VALUE (attr1), + TREE_VALUE (attr2)) == 1); + } + + if ((flag_openmp || flag_openmp_simd) + && TREE_VALUE (attr1) && TREE_VALUE (attr2) + && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE + && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE) + return omp_declare_simd_clauses_equal (TREE_VALUE (attr1), + TREE_VALUE (attr2)); + + return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1); +} + +/* Return 0 if the attributes for two types are incompatible, 1 if they + are compatible, and 2 if they are nearly compatible (which causes a + warning to be generated). */ +int +comp_type_attributes (const_tree type1, const_tree type2) +{ + const_tree a1 = TYPE_ATTRIBUTES (type1); + const_tree a2 = TYPE_ATTRIBUTES (type2); + const_tree a; + + if (a1 == a2) + return 1; + for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + const_tree attr; + + as = lookup_attribute_spec (get_attribute_name (a)); + if (!as || as->affects_type_identity == false) + continue; + + attr = lookup_attribute (as->name, CONST_CAST_TREE (a2)); + if (!attr || !attribute_value_equal (a, attr)) + break; + } + if (!a) + { + for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a)) + { + const struct attribute_spec *as; + + as = lookup_attribute_spec (get_attribute_name (a)); + if (!as || as->affects_type_identity == false) + continue; + + if (!lookup_attribute (as->name, CONST_CAST_TREE (a1))) + break; + /* We don't need to compare trees again, as we did this + already in first loop. */ + } + /* All types - affecting identity - are equal, so + there is no need to call target hook for comparison. */ + if (!a) + return 1; + } + if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a))) + return 0; + /* As some type combinations - like default calling-convention - might + be compatible, we have to call the target hook to get the final result. */ + return targetm.comp_type_attributes (type1, type2); +} + +/* Return a type like TTYPE except that its TYPE_ATTRIBUTE + is ATTRIBUTE. + + Record such modified types already made so we don't make duplicates. */ + +tree +build_type_attribute_variant (tree ttype, tree attribute) +{ + return build_type_attribute_qual_variant (ttype, attribute, + TYPE_QUALS (ttype)); +} + +/* A variant of lookup_attribute() that can be used with an identifier + as the first argument, and where the identifier can be either + 'text' or '__text__'. + + Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST, + return a pointer to the attribute's list element if the attribute + is part of the list, or NULL_TREE if not found. If the attribute + appears more than once, this only returns the first occurrence; the + TREE_CHAIN of the return value should be passed back in if further + occurrences are wanted. ATTR_IDENTIFIER must be an identifier but + can be in the form 'text' or '__text__'. */ +static tree +lookup_ident_attribute (tree attr_identifier, tree list) +{ + gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE); + + while (list) + { + gcc_checking_assert (TREE_CODE (get_attribute_name (list)) + == IDENTIFIER_NODE); + + if (cmp_attrib_identifiers (attr_identifier, + get_attribute_name (list))) + /* Found it. */ + break; + list = TREE_CHAIN (list); + } + + return list; +} + +/* Remove any instances of attribute ATTR_NAME in LIST and return the + modified list. */ + +tree +remove_attribute (const char *attr_name, tree list) +{ + tree *p; + gcc_checking_assert (attr_name[0] != '_'); + + for (p = &list; *p;) + { + tree l = *p; + + tree attr = get_attribute_name (l); + if (is_attribute_p (attr_name, attr)) + *p = TREE_CHAIN (l); + else + p = &TREE_CHAIN (l); + } + + return list; +} + +/* Return an attribute list that is the union of a1 and a2. */ + +tree +merge_attributes (tree a1, tree a2) +{ + tree attributes; + + /* Either one unset? Take the set one. */ + + if ((attributes = a1) == 0) + attributes = a2; + + /* One that completely contains the other? Take it. */ + + else if (a2 != 0 && ! attribute_list_contained (a1, a2)) + { + if (attribute_list_contained (a2, a1)) + attributes = a2; + else + { + /* Pick the longest list, and hang on the other list. */ + + if (list_length (a1) < list_length (a2)) + attributes = a2, a2 = a1; + + for (; a2 != 0; a2 = TREE_CHAIN (a2)) + { + tree a; + for (a = lookup_ident_attribute (get_attribute_name (a2), + attributes); + a != NULL_TREE && !attribute_value_equal (a, a2); + a = lookup_ident_attribute (get_attribute_name (a2), + TREE_CHAIN (a))) + ; + if (a == NULL_TREE) + { + a1 = copy_node (a2); + TREE_CHAIN (a1) = attributes; + attributes = a1; + } + } + } + } + return attributes; +} + +/* Given types T1 and T2, merge their attributes and return + the result. */ + +tree +merge_type_attributes (tree t1, tree t2) +{ + return merge_attributes (TYPE_ATTRIBUTES (t1), + TYPE_ATTRIBUTES (t2)); +} + +/* Given decls OLDDECL and NEWDECL, merge their attributes and return + the result. */ + +tree +merge_decl_attributes (tree olddecl, tree newdecl) +{ + return merge_attributes (DECL_ATTRIBUTES (olddecl), + DECL_ATTRIBUTES (newdecl)); +} + +#if TARGET_DLLIMPORT_DECL_ATTRIBUTES + +/* Specialization of merge_decl_attributes for various Windows targets. + + This handles the following situation: + + __declspec (dllimport) int foo; + int foo; + + The second instance of `foo' nullifies the dllimport. */ + +tree +merge_dllimport_decl_attributes (tree old, tree new_tree) +{ + tree a; + int delete_dllimport_p = 1; + + /* What we need to do here is remove from `old' dllimport if it doesn't + appear in `new'. dllimport behaves like extern: if a declaration is + marked dllimport and a definition appears later, then the object + is not dllimport'd. We also remove a `new' dllimport if the old list + contains dllexport: dllexport always overrides dllimport, regardless + of the order of declaration. */ + if (!VAR_OR_FUNCTION_DECL_P (new_tree)) + delete_dllimport_p = 0; + else if (DECL_DLLIMPORT_P (new_tree) + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) + { + DECL_DLLIMPORT_P (new_tree) = 0; + warning (OPT_Wattributes, "%q+D already declared with dllexport " + "attribute: dllimport ignored", new_tree); + } + else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree)) + { + /* Warn about overriding a symbol that has already been used, e.g.: + extern int __attribute__ ((dllimport)) foo; + int* bar () {return &foo;} + int foo; + */ + if (TREE_USED (old)) + { + warning (0, "%q+D redeclared without dllimport attribute " + "after being referenced with dll linkage", new_tree); + /* If we have used a variable's address with dllimport linkage, + keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the + decl may already have had TREE_CONSTANT computed. + We still remove the attribute so that assembler code refers + to '&foo rather than '_imp__foo'. */ + if (VAR_P (old) && TREE_ADDRESSABLE (old)) + DECL_DLLIMPORT_P (new_tree) = 1; + } + + /* Let an inline definition silently override the external reference, + but otherwise warn about attribute inconsistency. */ + else if (VAR_P (new_tree) || !DECL_DECLARED_INLINE_P (new_tree)) + warning (OPT_Wattributes, "%q+D redeclared without dllimport " + "attribute: previous dllimport ignored", new_tree); + } + else + delete_dllimport_p = 0; + + a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree)); + + if (delete_dllimport_p) + a = remove_attribute ("dllimport", a); + + return a; +} + +/* Handle a "dllimport" or "dllexport" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_dll_attribute (tree * pnode, tree name, tree args, int flags, + bool *no_add_attrs) +{ + tree node = *pnode; + bool is_dllimport; + + /* These attributes may apply to structure and union types being created, + but otherwise should pass to the declaration involved. */ + if (!DECL_P (node)) + { + if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT + | (int) ATTR_FLAG_ARRAY_NEXT)) + { + *no_add_attrs = true; + return tree_cons (name, args, NULL_TREE); + } + if (TREE_CODE (node) == RECORD_TYPE + || TREE_CODE (node) == UNION_TYPE) + { + node = TYPE_NAME (node); + if (!node) + return NULL_TREE; + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", + name); + *no_add_attrs = true; + return NULL_TREE; + } + } + + if (!VAR_OR_FUNCTION_DECL_P (node) && TREE_CODE (node) != TYPE_DECL) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qE attribute ignored", + name); + return NULL_TREE; + } + + if (TREE_CODE (node) == TYPE_DECL + && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE + && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE) + { + *no_add_attrs = true; + warning (OPT_Wattributes, "%qE attribute ignored", + name); + return NULL_TREE; + } + + is_dllimport = is_attribute_p ("dllimport", name); + + /* Report error on dllimport ambiguities seen now before they cause + any damage. */ + if (is_dllimport) + { + /* Honor any target-specific overrides. */ + if (!targetm.valid_dllimport_attribute_p (node)) + *no_add_attrs = true; + + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node)) + { + warning (OPT_Wattributes, "inline function %q+D declared as " + " dllimport: attribute ignored", node); + *no_add_attrs = true; + } + /* Like MS, treat definition of dllimported variables and + non-inlined functions on declaration as syntax errors. */ + else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)) + { + error ("function %q+D definition is marked dllimport", node); + *no_add_attrs = true; + } + + else if (VAR_P (node)) + { + if (DECL_INITIAL (node)) + { + error ("variable %q+D definition is marked dllimport", + node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + DECL_EXTERNAL (node) = 1; + /* Also, implicitly give dllimport'd variables declared within + a function global scope, unless declared static. */ + if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + } + + if (*no_add_attrs == false) + DECL_DLLIMPORT_P (node) = 1; + } + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node) + && flag_keep_inline_dllexport) + /* An exported function, even if inline, must be emitted. */ + DECL_EXTERNAL (node) = 0; + + /* Report error if symbol is not accessible at global scope. */ + if (!TREE_PUBLIC (node) && VAR_OR_FUNCTION_DECL_P (node)) + { + error ("external linkage required for symbol %q+D because of " + "%qE attribute", node, name); + *no_add_attrs = true; + } + + /* A dllexport'd entity must have default visibility so that other + program units (shared libraries or the main executable) can see + it. A dllimport'd entity must have default visibility so that + the linker knows that undefined references within this program + unit can be resolved by the dynamic linker. */ + if (!*no_add_attrs) + { + if (DECL_VISIBILITY_SPECIFIED (node) + && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT) + error ("%qE implies default visibility, but %qD has already " + "been declared with a different visibility", + name, node); + DECL_VISIBILITY (node) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (node) = 1; + } + + return NULL_TREE; +} + +#endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */ + +/* Given two lists of attributes, return true if list l2 is + equivalent to l1. */ + +int +attribute_list_equal (const_tree l1, const_tree l2) +{ + if (l1 == l2) + return 1; + + return attribute_list_contained (l1, l2) + && attribute_list_contained (l2, l1); +} + +/* Given two lists of attributes, return true if list L2 is + completely contained within L1. */ +/* ??? This would be faster if attribute names were stored in a canonicalized + form. Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method + must be used to show these elements are equivalent (which they are). */ +/* ??? It's not clear that attributes with arguments will always be handled + correctly. */ + +int +attribute_list_contained (const_tree l1, const_tree l2) +{ + const_tree t1, t2; + + /* First check the obvious, maybe the lists are identical. */ + if (l1 == l2) + return 1; + + /* Maybe the lists are similar. */ + for (t1 = l1, t2 = l2; + t1 != 0 && t2 != 0 + && get_attribute_name (t1) == get_attribute_name (t2) + && TREE_VALUE (t1) == TREE_VALUE (t2); + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) + ; + + /* Maybe the lists are equal. */ + if (t1 == 0 && t2 == 0) + return 1; + + for (; t2 != 0; t2 = TREE_CHAIN (t2)) + { + const_tree attr; + /* This CONST_CAST is okay because lookup_attribute does not + modify its argument and the return value is assigned to a + const_tree. */ + for (attr = lookup_ident_attribute (get_attribute_name (t2), + CONST_CAST_TREE (l1)); + attr != NULL_TREE && !attribute_value_equal (t2, attr); + attr = lookup_ident_attribute (get_attribute_name (t2), + TREE_CHAIN (attr))) + ; + + if (attr == NULL_TREE) + return 0; + } + + return 1; +} diff --git a/gcc/attribs.h b/gcc/attribs.h index 7f13332700ec1..06e6993e95820 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -47,4 +47,160 @@ extern char *make_unique_name (tree, const char *, bool); extern tree make_dispatcher_decl (const tree); extern bool is_function_default_version (const tree); +/* Return a type like TTYPE except that its TYPE_ATTRIBUTES + is ATTRIBUTE. + + Such modified types already made are recorded so that duplicates + are not made. */ + +extern tree build_type_attribute_variant (tree, tree); +extern tree build_decl_attribute_variant (tree, tree); +extern tree build_type_attribute_qual_variant (tree, tree, int); + +extern bool attribute_value_equal (const_tree, const_tree); + +/* Return 0 if the attributes for two types are incompatible, 1 if they + are compatible, and 2 if they are nearly compatible (which causes a + warning to be generated). */ +extern int comp_type_attributes (const_tree, const_tree); + +/* Default versions of target-overridable functions. */ +extern tree merge_decl_attributes (tree, tree); +extern tree merge_type_attributes (tree, tree); + +/* Remove any instances of attribute ATTR_NAME in LIST and return the + modified list. */ + +extern tree remove_attribute (const char *, tree); + +/* Given two attributes lists, return a list of their union. */ + +extern tree merge_attributes (tree, tree); + +/* Given two Windows decl attributes lists, possibly including + dllimport, return a list of their union . */ +extern tree merge_dllimport_decl_attributes (tree, tree); + +/* Handle a "dllimport" or "dllexport" attribute. */ +extern tree handle_dll_attribute (tree *, tree, tree, int, bool *); + +extern int attribute_list_equal (const_tree, const_tree); +extern int attribute_list_contained (const_tree, const_tree); + +/* For a given IDENTIFIER_NODE, strip leading and trailing '_' characters + so that we have a canonical form of attribute names. */ + +static inline tree +canonicalize_attr_name (tree attr_name) +{ + const size_t l = IDENTIFIER_LENGTH (attr_name); + const char *s = IDENTIFIER_POINTER (attr_name); + + if (l > 4 && s[0] == '_' && s[1] == '_' && s[l - 1] == '_' && s[l - 2] == '_') + return get_identifier_with_length (s + 2, l - 4); + + return attr_name; +} + +/* Compare attribute identifiers ATTR1 and ATTR2 with length ATTR1_LEN and + ATTR2_LEN. */ + +static inline bool +cmp_attribs (const char *attr1, size_t attr1_len, + const char *attr2, size_t attr2_len) +{ + return attr1_len == attr2_len && strncmp (attr1, attr2, attr1_len) == 0; +} + +/* Compare attribute identifiers ATTR1 and ATTR2. */ + +static inline bool +cmp_attribs (const char *attr1, const char *attr2) +{ + return cmp_attribs (attr1, strlen (attr1), attr2, strlen (attr2)); +} + +/* Given an identifier node IDENT and a string ATTR_NAME, return true + if the identifier node is a valid attribute name for the string. */ + +static inline bool +is_attribute_p (const char *attr_name, const_tree ident) +{ + return cmp_attribs (attr_name, strlen (attr_name), + IDENTIFIER_POINTER (ident), IDENTIFIER_LENGTH (ident)); +} + +/* Given an attribute name ATTR_NAME and a list of attributes LIST, + return a pointer to the attribute's list element if the attribute + is part of the list, or NULL_TREE if not found. If the attribute + appears more than once, this only returns the first occurrence; the + TREE_CHAIN of the return value should be passed back in if further + occurrences are wanted. ATTR_NAME must be in the form 'text' (not + '__text__'). */ + +static inline tree +lookup_attribute (const char *attr_name, tree list) +{ + gcc_checking_assert (attr_name[0] != '_'); + /* In most cases, list is NULL_TREE. */ + if (list == NULL_TREE) + return NULL_TREE; + else + { + size_t attr_len = strlen (attr_name); + /* Do the strlen() before calling the out-of-line implementation. + In most cases attr_name is a string constant, and the compiler + will optimize the strlen() away. */ + while (list) + { + tree attr = get_attribute_name (list); + size_t ident_len = IDENTIFIER_LENGTH (attr); + if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr), + ident_len)) + break; + list = TREE_CHAIN (list); + } + + return list; + } +} + +/* Given an attribute name ATTR_NAME and a list of attributes LIST, + return a pointer to the attribute's list first element if the attribute + starts with ATTR_NAME. ATTR_NAME must be in the form 'text' (not + '__text__'). */ + +static inline tree +lookup_attribute_by_prefix (const char *attr_name, tree list) +{ + gcc_checking_assert (attr_name[0] != '_'); + /* In most cases, list is NULL_TREE. */ + if (list == NULL_TREE) + return NULL_TREE; + else + { + size_t attr_len = strlen (attr_name); + while (list) + { + size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list)); + + if (attr_len > ident_len) + { + list = TREE_CHAIN (list); + continue; + } + + const char *p = IDENTIFIER_POINTER (get_attribute_name (list)); + gcc_checking_assert (attr_len == 0 || p[0] != '_'); + + if (strncmp (attr_name, p, attr_len) == 0) + break; + + list = TREE_CHAIN (list); + } + + return list; + } +} + #endif // GCC_ATTRIBS_H diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index dc50546ab63d4..4dad298fe596d 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -115,6 +115,8 @@ #include "bb-reorder.h" #include "except.h" #include "fibonacci_heap.h" +#include "stringpool.h" +#include "attribs.h" /* The number of rounds. In most cases there will only be 4 rounds, but when partitioning hot and cold basic blocks into separate sections of @@ -2904,7 +2906,8 @@ pass_partition_blocks::execute (function *fun) crossing_edges = find_rarely_executed_basic_blocks_and_crossing_edges (); if (!crossing_edges.exists ()) - return 0; + /* Make sure to process deferred rescans and clear changeable df flags. */ + return TODO_df_finish; crtl->has_bb_partition = true; @@ -2970,7 +2973,8 @@ pass_partition_blocks::execute (function *fun) df_analyze (); } - return 0; + /* Make sure to process deferred rescans and clear changeable df flags. */ + return TODO_df_finish; } } // anon namespace diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog index f7c82f4410749..08045329eeba1 100644 --- a/gcc/brig/ChangeLog +++ b/gcc/brig/ChangeLog @@ -1,3 +1,10 @@ +2017-08-04 Henry Linjamäki + + Fix PR 81713 + * brigfrontend/brig-basic-inst-handler.cc: replace build_int_cst with + bitsize_int in building BIT_FIELD_REF. + * brigfrontend/brig-code-entry-handler.cc: likewise. + 2017-07-05 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/brig/brigfrontend/brig-basic-inst-handler.cc b/gcc/brig/brigfrontend/brig-basic-inst-handler.cc index 68d81986f1cdc..8288d66551321 100644 --- a/gcc/brig/brigfrontend/brig-basic-inst-handler.cc +++ b/gcc/brig/brigfrontend/brig-basic-inst-handler.cc @@ -33,6 +33,7 @@ #include "stor-layout.h" #include "diagnostic-core.h" #include "brig-builtins.h" +#include "fold-const.h" brig_basic_inst_handler::brig_basic_inst_handler (brig_to_generic &parent) : brig_code_entry_handler (parent) @@ -112,10 +113,8 @@ brig_basic_inst_handler::build_shuffle (tree arith_type, { tree mask_element = build3 (BIT_FIELD_REF, mask_element_type, mask_operand, - build_int_cst (unsigned_char_type_node, - input_mask_element_size), - build_int_cst (unsigned_char_type_node, - i * input_mask_element_size)); + bitsize_int (input_mask_element_size), + bitsize_int (i * input_mask_element_size)); mask_element = convert (element_type, mask_element); diff --git a/gcc/brig/brigfrontend/brig-code-entry-handler.cc b/gcc/brig/brigfrontend/brig-code-entry-handler.cc index 906f47e76b3ec..8f07d372796ec 100644 --- a/gcc/brig/brigfrontend/brig-code-entry-handler.cc +++ b/gcc/brig/brigfrontend/brig-code-entry-handler.cc @@ -1423,9 +1423,8 @@ brig_code_entry_handler::build_output_assignment (const BrigInstBase &brig_inst, tree element_ref = build3 (BIT_FIELD_REF, element_type, input, TYPE_SIZE (element_type), - build_int_cst (uint32_type_node, - i * int_size_in_bytes (element_type) - * BITS_PER_UNIT)); + bitsize_int (i * int_size_in_bytes (element_type) + * BITS_PER_UNIT)); last_assign = build_output_assignment (brig_inst, element, element_ref); @@ -1488,7 +1487,7 @@ brig_code_entry_handler::unpack (tree value, tree_stl_vec &elements) tree element = build3 (BIT_FIELD_REF, input_element_type, value, TYPE_SIZE (input_element_type), - build_int_cst (unsigned_char_type_node, i * element_size)); + bitsize_int(i * element_size)); element = add_temp_var ("scalar", element); elements.push_back (element); @@ -1543,9 +1542,8 @@ tree_element_unary_visitor::operator () (brig_code_entry_handler &handler, { tree element = build3 (BIT_FIELD_REF, input_element_type, operand, TYPE_SIZE (input_element_type), - build_int_cst (unsigned_char_type_node, - i * element_size - * BITS_PER_UNIT)); + bitsize_int (i * element_size + * BITS_PER_UNIT)); tree output = visit_element (handler, element); output_element_type = TREE_TYPE (output); @@ -1594,15 +1592,13 @@ tree_element_binary_visitor::operator () (brig_code_entry_handler &handler, tree element0 = build3 (BIT_FIELD_REF, input_element_type, operand0, TYPE_SIZE (input_element_type), - build_int_cst (unsigned_char_type_node, - i * element_size - * BITS_PER_UNIT)); + bitsize_int (i * element_size + * BITS_PER_UNIT)); tree element1 = build3 (BIT_FIELD_REF, input_element_type, operand1, TYPE_SIZE (input_element_type), - build_int_cst (unsigned_char_type_node, - i * element_size - * BITS_PER_UNIT)); + bitsize_int (i * element_size + * BITS_PER_UNIT)); tree output = visit_element (handler, element0, element1); output_element_type = TREE_TYPE (output); diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index 53e67e62844af..336fd73e777b3 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -18,7 +18,10 @@ along with GCC; see the file COPYING3. If not see . */ /* This header provides a declarative way of describing the attributes - that are applied to some functions by default. + that are applied to some built-in functions by default. Attributes + that are meant to be used by user-defined functions but aren't used + by any built-ins, or attributes that apply to types or variables + but not to functions need not and should not be defined here. Before including this header, you must define the following macros. In each case where there is an ENUM, it is an identifier used to @@ -85,7 +88,9 @@ DEF_LIST_INT_INT (5,0) DEF_LIST_INT_INT (5,6) #undef DEF_LIST_INT_INT -/* Construct trees for identifiers. */ +/* Construct trees for identifiers used in built-in function attributes. + The construction contributes to startup costs so only attributes that + are used to define built-ins should be defined here. */ DEF_ATTR_IDENT (ATTR_ALLOC_SIZE, "alloc_size") DEF_ATTR_IDENT (ATTR_COLD, "cold") DEF_ATTR_IDENT (ATTR_CONST, "const") diff --git a/gcc/builtins.c b/gcc/builtins.c index 2deef725620b6..fa0f89c8f336f 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -60,6 +60,8 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "value-prof.h" #include "builtins.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" #include "cilk.h" #include "tree-chkp.h" @@ -121,12 +123,12 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode); static rtx expand_builtin_memchr (tree, rtx); static rtx expand_builtin_memcpy (tree, rtx); static rtx expand_builtin_memcpy_with_bounds (tree, rtx); -static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree); +static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, + rtx target, tree exp, int endp); static rtx expand_builtin_memmove (tree, rtx); -static rtx expand_builtin_mempcpy (tree, rtx, machine_mode); -static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode); -static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, - machine_mode, int, tree); +static rtx expand_builtin_mempcpy (tree, rtx); +static rtx expand_builtin_mempcpy_with_bounds (tree, rtx); +static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int); static rtx expand_builtin_strcat (tree, rtx); static rtx expand_builtin_strcpy (tree, rtx); static rtx expand_builtin_strcpy_args (tree, tree, rtx); @@ -2961,81 +2963,6 @@ determine_block_size (tree len, rtx len_rtx, GET_MODE_MASK (GET_MODE (len_rtx))); } -/* Helper function to do the actual work for expand_builtin_memcpy. */ - -static rtx -expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp) -{ - const char *src_str; - unsigned int src_align = get_pointer_alignment (src); - unsigned int dest_align = get_pointer_alignment (dest); - rtx dest_mem, src_mem, dest_addr, len_rtx; - HOST_WIDE_INT expected_size = -1; - unsigned int expected_align = 0; - unsigned HOST_WIDE_INT min_size; - unsigned HOST_WIDE_INT max_size; - unsigned HOST_WIDE_INT probable_max_size; - - /* If DEST is not a pointer type, call the normal function. */ - if (dest_align == 0) - return NULL_RTX; - - /* If either SRC is not a pointer type, don't do this - operation in-line. */ - if (src_align == 0) - return NULL_RTX; - - if (currently_expanding_gimple_stmt) - stringop_block_profile (currently_expanding_gimple_stmt, - &expected_align, &expected_size); - - if (expected_align < dest_align) - expected_align = dest_align; - dest_mem = get_memory_rtx (dest, len); - set_mem_align (dest_mem, dest_align); - len_rtx = expand_normal (len); - determine_block_size (len, len_rtx, &min_size, &max_size, - &probable_max_size); - src_str = c_getstr (src); - - /* If SRC is a string constant and block move would be done - by pieces, we can avoid loading the string from memory - and only stored the computed constants. */ - if (src_str - && CONST_INT_P (len_rtx) - && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 - && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, - CONST_CAST (char *, src_str), - dest_align, false)) - { - dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), - builtin_memcpy_read_str, - CONST_CAST (char *, src_str), - dest_align, false, 0); - dest_mem = force_operand (XEXP (dest_mem, 0), target); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; - } - - src_mem = get_memory_rtx (src, len); - set_mem_align (src_mem, src_align); - - /* Copy word part most expediently. */ - dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, - CALL_EXPR_TAILCALL (exp) - ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, - expected_align, expected_size, - min_size, max_size, probable_max_size); - - if (dest_addr == 0) - { - dest_addr = force_operand (XEXP (dest_mem, 0), target); - dest_addr = convert_memory_address (ptr_mode, dest_addr); - } - - return dest_addr; -} - /* Try to verify that the sizes and lengths of the arguments to a string manipulation function given by EXP are within valid bounds and that the operation does not lead to buffer overflow. Arguments other than @@ -3378,7 +3305,8 @@ expand_builtin_memcpy (tree exp, rtx target) check_memop_sizes (exp, dest, src, len); - return expand_builtin_memcpy_args (dest, src, len, target, exp); + return expand_builtin_memory_copy_args (dest, src, len, target, exp, + /*endp=*/ 0); } /* Check a call EXP to the memmove built-in for validity. @@ -3418,7 +3346,8 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) tree dest = CALL_EXPR_ARG (exp, 0); tree src = CALL_EXPR_ARG (exp, 2); tree len = CALL_EXPR_ARG (exp, 4); - rtx res = expand_builtin_memcpy_args (dest, src, len, target, exp); + rtx res = expand_builtin_memory_copy_args (dest, src, len, target, exp, + /*end_p=*/ 0); /* Return src bounds with the result. */ if (res) @@ -3440,7 +3369,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) stpcpy. */ static rtx -expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode) +expand_builtin_mempcpy (tree exp, rtx target) { if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) @@ -3457,8 +3386,7 @@ expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode) return NULL_RTX; return expand_builtin_mempcpy_args (dest, src, len, - target, mode, /*endp=*/ 1, - exp); + target, exp, /*endp=*/ 1); } /* Expand an instrumented call EXP to the mempcpy builtin. @@ -3467,7 +3395,7 @@ expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode) mode MODE if that's convenient). */ static rtx -expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode) +expand_builtin_mempcpy_with_bounds (tree exp, rtx target) { if (!validate_arglist (exp, POINTER_TYPE, POINTER_BOUNDS_TYPE, @@ -3480,7 +3408,7 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode) tree src = CALL_EXPR_ARG (exp, 2); tree len = CALL_EXPR_ARG (exp, 4); rtx res = expand_builtin_mempcpy_args (dest, src, len, target, - mode, 1, exp); + exp, 1); /* Return src bounds with the result. */ if (res) @@ -3493,94 +3421,103 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode) } } -/* Helper function to do the actual work for expand_builtin_mempcpy. The - arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out - so that this can also be called without constructing an actual CALL_EXPR. - The other arguments and return value are the same as for - expand_builtin_mempcpy. */ +/* Helper function to do the actual work for expand of memory copy family + functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes + of memory from SRC to DEST and assign to TARGET if convenient. + If ENDP is 0 return the + destination pointer, if ENDP is 1 return the end pointer ala + mempcpy, and if ENDP is 2 return the end pointer minus one ala + stpcpy. */ static rtx -expand_builtin_mempcpy_args (tree dest, tree src, tree len, - rtx target, machine_mode mode, int endp, - tree orig_exp) +expand_builtin_memory_copy_args (tree dest, tree src, tree len, + rtx target, tree exp, int endp) { - tree fndecl = get_callee_fndecl (orig_exp); + const char *src_str; + unsigned int src_align = get_pointer_alignment (src); + unsigned int dest_align = get_pointer_alignment (dest); + rtx dest_mem, src_mem, dest_addr, len_rtx; + HOST_WIDE_INT expected_size = -1; + unsigned int expected_align = 0; + unsigned HOST_WIDE_INT min_size; + unsigned HOST_WIDE_INT max_size; + unsigned HOST_WIDE_INT probable_max_size; - /* If return value is ignored, transform mempcpy into memcpy. */ - if (target == const0_rtx - && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP - && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP)) - { - tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP); - tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, - dest, src, len); - return expand_expr (result, target, mode, EXPAND_NORMAL); - } - else if (target == const0_rtx - && builtin_decl_implicit_p (BUILT_IN_MEMCPY)) - { - tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY); - tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, - dest, src, len); - return expand_expr (result, target, mode, EXPAND_NORMAL); - } - else - { - const char *src_str; - unsigned int src_align = get_pointer_alignment (src); - unsigned int dest_align = get_pointer_alignment (dest); - rtx dest_mem, src_mem, len_rtx; + /* If DEST is not a pointer type, call the normal function. */ + if (dest_align == 0) + return NULL_RTX; - /* If either SRC or DEST is not a pointer type, don't do this - operation in-line. */ - if (dest_align == 0 || src_align == 0) - return NULL_RTX; + /* If either SRC is not a pointer type, don't do this + operation in-line. */ + if (src_align == 0) + return NULL_RTX; - /* If LEN is not constant, call the normal function. */ - if (! tree_fits_uhwi_p (len)) - return NULL_RTX; + if (currently_expanding_gimple_stmt) + stringop_block_profile (currently_expanding_gimple_stmt, + &expected_align, &expected_size); - len_rtx = expand_normal (len); - src_str = c_getstr (src); + if (expected_align < dest_align) + expected_align = dest_align; + dest_mem = get_memory_rtx (dest, len); + set_mem_align (dest_mem, dest_align); + len_rtx = expand_normal (len); + determine_block_size (len, len_rtx, &min_size, &max_size, + &probable_max_size); + src_str = c_getstr (src); - /* If SRC is a string constant and block move would be done - by pieces, we can avoid loading the string from memory - and only stored the computed constants. */ - if (src_str - && CONST_INT_P (len_rtx) - && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 - && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, + /* If SRC is a string constant and block move would be done + by pieces, we can avoid loading the string from memory + and only stored the computed constants. */ + if (src_str + && CONST_INT_P (len_rtx) + && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 + && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, + CONST_CAST (char *, src_str), + dest_align, false)) + { + dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), + builtin_memcpy_read_str, CONST_CAST (char *, src_str), - dest_align, false)) - { - dest_mem = get_memory_rtx (dest, len); - set_mem_align (dest_mem, dest_align); - dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), - builtin_memcpy_read_str, - CONST_CAST (char *, src_str), - dest_align, false, endp); - dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; - } + dest_align, false, endp); + dest_mem = force_operand (XEXP (dest_mem, 0), target); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; + } - if (CONST_INT_P (len_rtx) - && can_move_by_pieces (INTVAL (len_rtx), - MIN (dest_align, src_align))) - { - dest_mem = get_memory_rtx (dest, len); - set_mem_align (dest_mem, dest_align); - src_mem = get_memory_rtx (src, len); - set_mem_align (src_mem, src_align); - dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx), - MIN (dest_align, src_align), endp); - dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; - } + src_mem = get_memory_rtx (src, len); + set_mem_align (src_mem, src_align); - return NULL_RTX; + /* Copy word part most expediently. */ + dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, + CALL_EXPR_TAILCALL (exp) + && (endp == 0 || target == const0_rtx) + ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, + expected_align, expected_size, + min_size, max_size, probable_max_size); + + if (dest_addr == 0) + { + dest_addr = force_operand (XEXP (dest_mem, 0), target); + dest_addr = convert_memory_address (ptr_mode, dest_addr); } + + if (endp && target != const0_rtx) + { + dest_addr = gen_rtx_PLUS (ptr_mode, dest_addr, len_rtx); + /* stpcpy pointer to last byte. */ + if (endp == 2) + dest_addr = gen_rtx_MINUS (ptr_mode, dest_addr, const1_rtx); + } + + return dest_addr; +} + +static rtx +expand_builtin_mempcpy_args (tree dest, tree src, tree len, + rtx target, tree orig_exp, int endp) +{ + return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp, + endp); } /* Expand into a movstr instruction, if one is available. Return NULL_RTX if @@ -3738,8 +3675,7 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode) lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); ret = expand_builtin_mempcpy_args (dst, src, lenp1, - target, mode, /*endp=*/2, - exp); + target, exp, /*endp=*/2); if (ret) return ret; @@ -6902,7 +6838,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, break; case BUILT_IN_MEMPCPY: - target = expand_builtin_mempcpy (exp, target, mode); + target = expand_builtin_mempcpy (exp, target); if (target) return target; break; @@ -7681,7 +7617,7 @@ expand_builtin_with_bounds (tree exp, rtx target, break; case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP: - target = expand_builtin_mempcpy_with_bounds (exp, target, mode); + target = expand_builtin_mempcpy_with_bounds (exp, target); if (target) return target; break; diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1b6d7cfb903ee..fc5a807ccfef9 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,132 @@ +2017-08-29 Martin Liska + + PR other/39851 + * c-common.c (parse_optimize_options): Add argument to function + call. + * c-pragma.c (handle_pragma_diagnostic): Likewise. + +2017-08-24 David Malcolm + + * c-lex.c (interpret_float): Use token location + when building an EXCESS_PRECISION_EXPR. + +2017-08-21 David Malcolm + + * c-common.c (check_function_arguments): Add "arglogs" param; pass + it to check_function_format. + * c-common.h (check_function_arguments): Add vec * + param. + (check_function_format): Likewise. + * c-format.c (struct format_check_context): Add field "arglocs". + (check_function_format): Add param "arglocs"; pass it to + check_format_info. + (check_format_info): Add param "arglocs"; use it to initialize + new field of format_ctx. + (check_format_arg): Pass format_ctx->arglocs to new param of + check_format_info_main. + (class argument_parser): New field "arglocs". + (argument_parser::argument_parser): Add "arglocs_" param and use + it to initialize new field. + (argument_parser::check_argument_type): Pass new arglocs field to + check_format_types. + (check_format_info_main): Add param "arglocs", and use it when + constructing arg_parser. + (check_format_types): Add param "arglocs"; use it if non-NULL when + !EXPR_HAS_LOCATION (cur_param) to get at location information. + +2017-08-18 H.J. Lu + + PR c/53037 + * c-attribs.c (handle_warn_if_not_aligned_attribute): New. + (c_common_attribute_table): Add warn_if_not_aligned. + (handle_aligned_attribute): Renamed to ... + (common_handle_aligned_attribute): Remove argument, name, and add + argument, warn_if_not_aligned. Handle warn_if_not_aligned. + (handle_aligned_attribute): New. + * c.opt: Add -Wif-not-aligned and -Wpacked-not-aligned. + +2017-08-14 Martin Sebor + + PR c/81117 + * c-attribs.c (c_common_attribute_table): Add nonstring entry. + (handle_nonstring_attribute): New function. + +2017-08-14 Martin Sebor + + PR c/81117 + * c-format.h (T89_G): New macro. + * c-format.c (local_gcall_ptr_node): New variable. + (init_dynamic_diag_info): Initialize it. + +2017-08-11 Martin Liska + + * c-opts.c (c_common_post_options): Replace ASM_OUTPUT_DEF with + TARGET_SUPPORTS_ALIASES. + +2017-08-10 David Malcolm + + * c-common.c (c_parse_error): Add rich_location * param, using it + rather implicitly using input_location. + * c-common.h (c_parse_error): Add rich_location * param. + +2017-08-09 Marek Polacek + + * c-common.c (pointer_int_sum): Use true/false instead of 1/0. + (c_common_truthvalue_conversion): Likewise. + * c-omp.c (c_finish_omp_atomic): Likewise. + * c-common.h (build_binary_op): Update declaration. + +2017-08-08 Martin Liska + + * c-ada-spec.c: Include header files. + * c-ubsan.c: Likewise. + * c-warn.c: Likewise. + +2017-08-07 Jakub Jelinek + + PR c/69389 + * c-omp.c (c_finish_omp_atomic): Handle atomics on bitfields. + +2017-08-07 Eric Botcazou + + * c-ada-spec.c (has_nontrivial_methods): Test for FUNCTION_DECL. + (print_ada_methods): Likewise. + (print_ada_declaration): Likewise. + +2017-08-07 Martin Liska + + * array-notation-common.c: Add new includes. + * c-format.c( handle_format_attribute): Canonicalize a format + function name. + * c-lex.c (c_common_has_attribute): Canonicalize name of an + attribute. + * c-pretty-print.c: Add new include. + +2017-08-05 Eric Botcazou + + * c-ada-spec.c (has_static_fields): Look only into variables. + (print_constructor): Add TYPE parameter and use it for the name. + (print_destructor): Likewise. + (print_ada_declaration): Adjust to new constructor/destructor names. + Adjust calls to print_constructor and print_destructor. + (print_ada_struct_decl): Do not test TREE_STATIC on FIELD_DECL. + Look only into variables in the final loop. + +2017-08-01 Eric Botcazou + + * c-ada-spec.c (has_static_fields): Look only into fields. + (dump_generic_ada_node): Small tweak. + (dump_nested_types): Look only into fields. + (print_ada_declaration): Look only into methods. Small tweak. + (print_ada_struct_decl): Look only into fields. Use DECL_VIRTUAL_P. + +2017-08-01 Eric Botcazou + + * c-ada-spec.c (print_generic_ada_decl): Pass correctly-typed constant. + (dump_ada_function_declaration): Likewise. + (dump_generic_ada_node): Likewise. + (print_ada_declaration): Add support for const-qualified variables. + 2017-07-31 Martin Liska PR sanitize/81530 diff --git a/gcc/c-family/array-notation-common.c b/gcc/c-family/array-notation-common.c index 3b95332adadb4..a4809948e2036 100644 --- a/gcc/c-family/array-notation-common.c +++ b/gcc/c-family/array-notation-common.c @@ -27,6 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "c-family/c-common.h" #include "tree-iterator.h" +#include "stringpool.h" +#include "attribs.h" /* Returns true if the function call in FNDECL is __sec_implicit_index. */ diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index de549501440e2..0cd3d55b55b0f 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "c-pragma.h" #include "cpp-id-data.h" +#include "stringpool.h" +#include "attribs.h" /* Local functions, macros and variables. */ static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int, @@ -858,7 +860,7 @@ print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file) { source_file_base = source_file; - if (print_ada_declaration (pp, decl, 0, INDENT_INCR)) + if (print_ada_declaration (pp, decl, NULL_TREE, INDENT_INCR)) { pp_newline (pp); pp_newline (pp); @@ -1052,13 +1054,11 @@ get_underlying_decl (tree type) static bool has_static_fields (const_tree type) { - tree tmp; - if (!type || !RECORD_OR_UNION_TYPE_P (type)) return false; - for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp)) - if (DECL_NAME (tmp) && TREE_STATIC (tmp)) + for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld)) + if (TREE_CODE (fld) == VAR_DECL && DECL_NAME (fld)) return true; return false; @@ -1101,7 +1101,7 @@ has_nontrivial_methods (tree type) /* If there are user-defined methods, they are deemed non-trivial. */ for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) - if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE && !DECL_ARTIFICIAL (fld)) + if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld)) return true; return false; @@ -1655,7 +1655,8 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, if (DECL_NAME (arg)) { check_name (buffer, arg); - pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false); + pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, + false); pp_string (buffer, " : "); } else @@ -2096,7 +2097,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc, { if (DECL_NAME (node)) pp_ada_tree_identifier - (buffer, DECL_NAME (node), 0, limited_access); + (buffer, DECL_NAME (node), NULL_TREE, limited_access); else pp_string (buffer, ""); } @@ -2383,13 +2384,14 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc, { if (is_tagged_type (TREE_TYPE (node))) { - tree tmp = TYPE_FIELDS (TREE_TYPE (node)); int first = 1; /* Look for ancestors. */ - for (; tmp; tmp = TREE_CHAIN (tmp)) + for (tree fld = TYPE_FIELDS (TREE_TYPE (node)); + fld; + fld = TREE_CHAIN (fld)) { - if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp))) + if (!DECL_NAME (fld) && is_tagged_type (TREE_TYPE (fld))) { if (first) { @@ -2399,8 +2401,8 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc, else pp_string (buffer, " and "); - dump_ada_decl_name - (buffer, TYPE_NAME (TREE_TYPE (tmp)), false); + dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (fld)), + false); } } @@ -2442,7 +2444,7 @@ print_ada_methods (pretty_printer *buffer, tree node, int spc) int res = 1; for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld)) - if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE) + if (TREE_CODE (fld) == FUNCTION_DECL) { if (res) { @@ -2503,7 +2505,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, dump_nested_type (buffer, field, t, parent, spc); for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (!TYPE_NAME (TREE_TYPE (field))) + if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field))) dump_nested_type (buffer, field, t, parent, spc); TREE_VISITED (t) = 1; @@ -2635,12 +2637,12 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, } } -/* Dump in BUFFER constructor spec corresponding to T. */ +/* Dump in BUFFER constructor spec corresponding to T for TYPE. */ static void -print_constructor (pretty_printer *buffer, tree t) +print_constructor (pretty_printer *buffer, tree t, tree type) { - tree decl_name = DECL_NAME (DECL_ORIGIN (t)); + tree decl_name = DECL_NAME (TYPE_NAME (type)); pp_string (buffer, "New_"); pp_ada_tree_identifier (buffer, decl_name, t, false); @@ -2649,9 +2651,9 @@ print_constructor (pretty_printer *buffer, tree t) /* Dump in BUFFER destructor spec corresponding to T. */ static void -print_destructor (pretty_printer *buffer, tree t) +print_destructor (pretty_printer *buffer, tree t, tree type) { - tree decl_name = DECL_NAME (DECL_ORIGIN (t)); + tree decl_name = DECL_NAME (TYPE_NAME (type)); pp_string (buffer, "Delete_"); pp_ada_tree_identifier (buffer, decl_name, t, false); @@ -2907,7 +2909,8 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) return 0; /* Only consider constructors/destructors for complete objects. */ - if (strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6) != 0) + if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0 + && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0) return 0; } @@ -2935,9 +2938,9 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) } if (is_constructor) - print_constructor (buffer, t); + print_constructor (buffer, t, type); else if (is_destructor) - print_destructor (buffer, t); + print_destructor (buffer, t, type); else dump_ada_decl_name (buffer, t, false); @@ -2954,7 +2957,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (is_constructor && RECORD_OR_UNION_TYPE_P (type)) for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) - if (cpp_check (fld, IS_ABSTRACT)) + if (TREE_CODE (fld) == FUNCTION_DECL && cpp_check (fld, IS_ABSTRACT)) { is_abstract_class = true; break; @@ -2975,7 +2978,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (is_constructor) { pp_string (buffer, "pragma CPP_Constructor ("); - print_constructor (buffer, t); + print_constructor (buffer, t, type); pp_string (buffer, ", \""); pp_asm_name (buffer, t); pp_string (buffer, "\");"); @@ -2983,7 +2986,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) else if (is_destructor) { pp_string (buffer, "pragma Import (CPP, "); - print_destructor (buffer, t); + print_destructor (buffer, t, type); pp_string (buffer, ", \""); pp_asm_name (buffer, t); pp_string (buffer, "\");"); @@ -3019,20 +3022,22 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (cpp_check && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))) { - is_interface = -1; + bool has_fields = false; /* Check that there are no fields other than the virtual table. */ for (tree fld = TYPE_FIELDS (TREE_TYPE (t)); - fld; fld = TREE_CHAIN (fld)) + fld; + fld = TREE_CHAIN (fld)) { if (TREE_CODE (fld) == FIELD_DECL) { - if (is_interface < 0 && DECL_VIRTUAL_P (fld)) + if (!has_fields && DECL_VIRTUAL_P (fld)) is_interface = 1; else is_interface = 0; + has_fields = true; } - else if (TREE_CODE (TREE_TYPE (fld)) == METHOD_TYPE + else if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld)) { if (cpp_check (fld, IS_ABSTRACT)) @@ -3097,6 +3102,9 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) { pp_string (buffer, "aliased "); + if (TREE_READONLY (t)) + pp_string (buffer, "constant "); + if (TYPE_NAME (TREE_TYPE (t))) dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true); @@ -3110,6 +3118,9 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE)) pp_string (buffer, "aliased "); + if (TREE_READONLY (t)) + pp_string (buffer, "constant "); + dump_generic_ada_node (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true); } @@ -3205,10 +3216,10 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc, field_num++; } } - else if (TREE_CODE (tmp) != TYPE_DECL && !TREE_STATIC (tmp)) + else if (TREE_CODE (tmp) == FIELD_DECL) { /* Skip internal virtual table field. */ - if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5)) + if (!DECL_VIRTUAL_P (tmp)) { if (is_union) { @@ -3299,7 +3310,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc, /* Print the static fields of the structure, if any. */ for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp)) { - if (DECL_NAME (tmp) && TREE_STATIC (tmp)) + if (TREE_CODE (tmp) == VAR_DECL && DECL_NAME (tmp)) { if (need_semicolon) { diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 0d9ab2d6ae037..5f79468407f6d 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -89,6 +89,8 @@ static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); static tree handle_mode_attribute (tree *, tree, tree, int, bool *); static tree handle_section_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, + int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -116,6 +118,7 @@ static tree handle_deprecated_attribute (tree *, tree, tree, int, static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *); static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nonstring_attribute (tree *, tree, tree, int, bool *); static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, @@ -216,6 +219,9 @@ const struct attribute_spec c_common_attribute_table[] = handle_section_attribute, false }, { "aligned", 0, 1, false, false, false, handle_aligned_attribute, false }, + { "warn_if_not_aligned", 0, 1, false, false, false, + handle_warn_if_not_aligned_attribute, + false }, { "weak", 0, 0, true, false, false, handle_weak_attribute, false }, { "noplt", 0, 0, true, false, false, @@ -270,6 +276,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_tls_model_attribute, false }, { "nonnull", 0, -1, false, true, true, handle_nonnull_attribute, false }, + { "nonstring", 0, 0, true, false, false, + handle_nonstring_attribute, false }, { "nothrow", 0, 0, true, false, false, handle_nothrow_attribute, false }, { "may_alias", 0, 0, false, true, false, NULL, false }, @@ -1663,12 +1671,13 @@ check_cxx_fundamental_alignment_constraints (tree node, return !alignment_too_large_p; } -/* Handle a "aligned" attribute; arguments as in - struct attribute_spec.handler. */ +/* Common codes shared by handle_warn_if_not_aligned_attribute and + handle_aligned_attribute. */ static tree -handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, - int flags, bool *no_add_attrs) +common_handle_aligned_attribute (tree *node, tree args, int flags, + bool *no_add_attrs, + bool warn_if_not_aligned_p) { tree decl = NULL_TREE; tree *type = NULL; @@ -1717,8 +1726,16 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, else *type = build_variant_type_copy (*type); - SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT); - TYPE_USER_ALIGN (*type) = 1; + if (warn_if_not_aligned_p) + { + SET_TYPE_WARN_IF_NOT_ALIGN (*type, (1U << i) * BITS_PER_UNIT); + warn_if_not_aligned_p = false; + } + else + { + SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT); + TYPE_USER_ALIGN (*type) = 1; + } } else if (! VAR_OR_FUNCTION_DECL_P (decl) && TREE_CODE (decl) != FIELD_DECL) @@ -1751,13 +1768,54 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, } else { - SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT); - DECL_USER_ALIGN (decl) = 1; + if (warn_if_not_aligned_p) + { + if (TREE_CODE (decl) == FIELD_DECL && !DECL_INITIAL (decl)) + { + SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT); + warn_if_not_aligned_p = false; + } + } + else + { + SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT); + DECL_USER_ALIGN (decl) = 1; + } + } + + if (warn_if_not_aligned_p) + { + error ("% may not be specified for %q+D", + decl); + *no_add_attrs = true; } return NULL_TREE; } +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + return common_handle_aligned_attribute (node, args, flags, + no_add_attrs, false); +} + +/* Handle a "warn_if_not_aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_warn_if_not_aligned_attribute (tree *node, tree ARG_UNUSED (name), + tree args, int flags, + bool *no_add_attrs) +{ + return common_handle_aligned_attribute (node, args, flags, + no_add_attrs, true); +} + /* Handle a "weak" attribute; arguments as in struct attribute_spec.handler. */ @@ -2970,6 +3028,48 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), return NULL_TREE; } +/* Handle the "nonstring" variable attribute. */ + +static tree +handle_nonstring_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + gcc_assert (!args); + tree_code code = TREE_CODE (*node); + + if (VAR_P (*node) + || code == FIELD_DECL + || code == PARM_DECL) + { + tree type = TREE_TYPE (*node); + + if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) + { + tree eltype = TREE_TYPE (type); + if (eltype == char_type_node) + return NULL_TREE; + } + + warning (OPT_Wattributes, + "%qE attribute ignored on objects of type %qT", + name, type); + *no_add_attrs = true; + return NULL_TREE; + } + + if (code == FUNCTION_DECL) + warning (OPT_Wattributes, + "%qE attribute does not apply to functions", name); + else if (code == TYPE_DECL) + warning (OPT_Wattributes, + "%qE attribute does not apply to types", name); + else + warning (OPT_Wattributes, "%qE attribute ignored", name); + + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "nothrow" attribute; arguments as in struct attribute_spec.handler. */ @@ -3139,6 +3239,19 @@ handle_target_attribute (tree *node, tree name, tree args, int flags, flags)) *no_add_attrs = true; + /* Check that there's no empty string in values of the attribute. */ + for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t)) + { + tree value = TREE_VALUE (t); + if (TREE_CODE (value) == STRING_CST + && TREE_STRING_LENGTH (value) == 1 + && TREE_STRING_POINTER (value)[0] == '\0') + { + warning (OPT_Wattributes, "empty string in attribute %"); + *no_add_attrs = true; + } + } + return NULL_TREE; } diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index feb0904bcbf49..f4f2819aeceee 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -3133,7 +3133,8 @@ pointer_int_sum (location_t loc, enum tree_code resultcode, can result in a sum or difference with different type args. */ ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)), subcode, ptrop, - convert (int_type, TREE_OPERAND (intop, 1)), 1); + convert (int_type, TREE_OPERAND (intop, 1)), + true); intop = convert (int_type, TREE_OPERAND (intop, 0)); } @@ -3306,7 +3307,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) TREE_OPERAND (expr, 0)), c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 1)), - 0); + false); goto ret; case NEGATE_EXPR: @@ -3457,7 +3458,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) c_common_truthvalue_conversion (location, build_unary_op (location, IMAGPART_EXPR, t, false)), - 0)); + false)); goto ret; } @@ -3466,10 +3467,10 @@ c_common_truthvalue_conversion (location_t location, tree expr) tree fixed_zero_node = build_fixed (TREE_TYPE (expr), FCONST0 (TYPE_MODE (TREE_TYPE (expr)))); - return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, 1); + return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, true); } else - return build_binary_op (location, NE_EXPR, expr, integer_zero_node, 1); + return build_binary_op (location, NE_EXPR, expr, integer_zero_node, true); ret: protected_set_expr_location (expr, location); @@ -5496,7 +5497,7 @@ parse_optimize_options (tree args, bool attr_p) /* And apply them. */ decode_options (&global_options, &global_options_set, decoded_options, decoded_options_count, - input_location, global_dc); + input_location, global_dc, NULL); targetm.override_options_after_change(); @@ -5538,7 +5539,7 @@ attribute_fallthrough_p (tree attr) diagnostics. Return true if -Wnonnull warning has been diagnosed. */ bool check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, - int nargs, tree *argarray) + int nargs, tree *argarray, vec *arglocs) { bool warned_p = false; @@ -5552,7 +5553,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, /* Check for errors in format strings. */ if (warn_format || warn_suggest_attribute_format) - check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray); + check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray, arglocs); if (warn_format) check_function_sentinel (fntype, nargs, argarray); @@ -5949,12 +5950,13 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size) return result; } -/* Issue the error given by GMSGID, indicating that it occurred before - TOKEN, which had the associated VALUE. */ +/* Issue the error given by GMSGID at RICHLOC, indicating that it occurred + before TOKEN, which had the associated VALUE. */ void c_parse_error (const char *gmsgid, enum cpp_ttype token_type, - tree value, unsigned char token_flags) + tree value, unsigned char token_flags, + rich_location *richloc) { #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2)) @@ -5995,7 +5997,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, else message = catenate_messages (gmsgid, " before %s'\\x%x'"); - error (message, prefix, val); + error_at_rich_loc (richloc, message, prefix, val); free (message); message = NULL; } @@ -6023,7 +6025,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, else if (token_type == CPP_NAME) { message = catenate_messages (gmsgid, " before %qE"); - error (message, value); + error_at_rich_loc (richloc, message, value); free (message); message = NULL; } @@ -6036,16 +6038,16 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, else if (token_type < N_TTYPES) { message = catenate_messages (gmsgid, " before %qs token"); - error (message, cpp_type2name (token_type, token_flags)); + error_at_rich_loc (richloc, message, cpp_type2name (token_type, token_flags)); free (message); message = NULL; } else - error (gmsgid); + error_at_rich_loc (richloc, gmsgid); if (message) { - error (message); + error_at_rich_loc (richloc, message); free (message); } #undef catenate_messages diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index a29f1ade25d66..8e36768060033 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -808,7 +808,7 @@ extern tree fname_decl (location_t, unsigned, tree); extern int check_user_alignment (const_tree, bool); extern bool check_function_arguments (location_t loc, const_tree, const_tree, - int, tree *); + int, tree *, vec *); extern void check_function_arguments_recurse (void (*) (void *, tree, unsigned HOST_WIDE_INT), @@ -816,7 +816,7 @@ extern void check_function_arguments_recurse (void (*) unsigned HOST_WIDE_INT); extern bool check_builtin_function_arguments (location_t, vec, tree, int, tree *); -extern void check_function_format (tree, int, tree *); +extern void check_function_format (tree, int, tree *, vec *); extern bool attribute_fallthrough_p (tree); extern tree handle_format_attribute (tree *, tree, tree, int, bool *); extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *); @@ -960,7 +960,7 @@ extern tree build_real_imag_expr (location_t, enum tree_code, tree); a variant of the C language. They are used in c-common.c. */ extern tree build_unary_op (location_t, enum tree_code, tree, bool); -extern tree build_binary_op (location_t, enum tree_code, tree, tree, int); +extern tree build_binary_op (location_t, enum tree_code, tree, tree, bool); extern tree perform_integral_promotions (tree); /* These functions must be defined by each front-end which implements @@ -1124,7 +1124,8 @@ extern void builtin_define_with_int_value (const char *, HOST_WIDE_INT); extern void builtin_define_type_sizeof (const char *, tree); extern void c_stddef_cpp_builtins (void); extern void fe_file_change (const line_map_ordinary *); -extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char); +extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char, + rich_location *richloc); /* In c-ppoutput.c */ extern void init_pp_output (FILE *); diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index 0a5cc03fd4e99..0dba9793311b7 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "substring-locations.h" #include "selftest.h" #include "builtins.h" +#include "attribs.h" /* Handle attributes associated with format checking. */ @@ -55,6 +56,7 @@ struct function_format_info /* Initialized in init_dynamic_diag_info. */ static GTY(()) tree local_tree_type_node; +static GTY(()) tree local_gcall_ptr_node; static GTY(()) tree locus; static bool decode_format_attr (tree, function_format_info *, int); @@ -67,7 +69,6 @@ static bool check_format_string (tree argument, static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p); static const char *convert_format_name_to_system_name (const char *attr_name); -static bool cmp_attribs (const char *tattr_name, const char *attr_name); static int first_target_format_type; static const char *format_name (int format_num); @@ -689,7 +690,9 @@ static const format_char_info gcc_diag_char_table[] = /* Custom conversion specifiers. */ - /* These will require a "tree" at runtime. */ + /* G requires a "gcall*" argument at runtime. */ + { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + /* K requires a "tree" argument at runtime. */ { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, @@ -718,6 +721,9 @@ static const format_char_info gcc_tdiag_char_table[] = { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + /* G requires a "gcall*" argument at runtime. */ + { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, @@ -747,6 +753,9 @@ static const format_char_info gcc_cdiag_char_table[] = { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + /* G requires a "gcall*" argument at runtime. */ + { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, @@ -777,6 +786,9 @@ static const format_char_info gcc_cxxdiag_char_table[] = { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, + /* G requires a "gcall*" argument at runtime. */ + { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, + /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, @@ -977,6 +989,7 @@ struct format_check_context format_check_results *res; function_format_info *info; tree params; + vec *arglocs; }; /* Return the format name (as specified in the original table) for the format @@ -999,14 +1012,16 @@ format_flags (int format_num) gcc_unreachable (); } -static void check_format_info (function_format_info *, tree); +static void check_format_info (function_format_info *, tree, + vec *); static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); static void check_format_info_main (format_check_results *, function_format_info *, const char *, location_t, tree, int, tree, unsigned HOST_WIDE_INT, - object_allocator &); + object_allocator &, + vec *); static void init_dollar_format_checking (int, tree); static int maybe_read_dollar_number (const char **, int, @@ -1021,7 +1036,8 @@ static void check_format_types (const substring_loc &fmt_loc, format_wanted_type *, const format_kind_info *fki, int offset_to_type_start, - char conversion_char); + char conversion_char, + vec *arglocs); static void format_type_warning (const substring_loc &fmt_loc, source_range *param_range, format_wanted_type *, tree, @@ -1064,7 +1080,8 @@ decode_format_type (const char *s) attribute themselves. */ void -check_function_format (tree attrs, int nargs, tree *argarray) +check_function_format (tree attrs, int nargs, tree *argarray, + vec *arglocs) { tree a; @@ -1085,7 +1102,7 @@ check_function_format (tree attrs, int nargs, tree *argarray) int i; for (i = nargs - 1; i >= 0; i--) params = tree_cons (NULL_TREE, argarray[i], params); - check_format_info (&info, params); + check_format_info (&info, params, arglocs); } /* Attempt to detect whether the current function might benefit @@ -1388,7 +1405,8 @@ get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates) PARAMS is the list of argument values. */ static void -check_format_info (function_format_info *info, tree params) +check_format_info (function_format_info *info, tree params, + vec *arglocs) { format_check_context format_ctx; unsigned HOST_WIDE_INT arg_num; @@ -1422,6 +1440,7 @@ check_format_info (function_format_info *info, tree params) format_ctx.res = &res; format_ctx.info = info; format_ctx.params = params; + format_ctx.arglocs = arglocs; check_function_arguments_recurse (check_format_arg, &format_ctx, format_tree, arg_num); @@ -1506,6 +1525,7 @@ check_format_arg (void *ctx, tree format_tree, format_check_results *res = format_ctx->res; function_format_info *info = format_ctx->info; tree params = format_ctx->params; + vec *arglocs = format_ctx->arglocs; int format_length; HOST_WIDE_INT offset; @@ -1691,7 +1711,7 @@ check_format_arg (void *ctx, tree format_tree, res->number_other++; object_allocator fwt_pool ("format_wanted_type pool"); check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree, - format_length, params, arg_num, fwt_pool); + format_length, params, arg_num, fwt_pool, arglocs); } /* Support class for argument_parser and check_format_info_main. @@ -1756,7 +1776,8 @@ class argument_parser const char * const orig_format_chars, location_t format_string_loc, flag_chars_t &flag_chars, int &has_operand_number, tree first_fillin_param, - object_allocator &fwt_pool_); + object_allocator &fwt_pool_, + vec *arglocs); bool read_any_dollar (); @@ -1835,6 +1856,7 @@ class argument_parser private: format_wanted_type *first_wanted_type; format_wanted_type *last_wanted_type; + vec *arglocs; }; /* flag_chars_t's constructor. */ @@ -1985,7 +2007,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_, flag_chars_t &flag_chars_, int &has_operand_number_, tree first_fillin_param_, - object_allocator &fwt_pool_) + object_allocator &fwt_pool_, + vec *arglocs_) : info (info_), fki (&format_types[info->format_type]), flag_specs (fki->flag_specs), @@ -2001,7 +2024,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_, has_operand_number (has_operand_number_), first_fillin_param (first_fillin_param_), first_wanted_type (NULL), - last_wanted_type (NULL) + last_wanted_type (NULL), + arglocs (arglocs_) { } @@ -2724,7 +2748,7 @@ check_argument_type (const format_char_info *fci, ptrdiff_t offset_to_type_start = type_start - orig_format_chars; check_format_types (fmt_loc, first_wanted_type, fki, offset_to_type_start, - conversion_char); + conversion_char, arglocs); } return true; @@ -2743,7 +2767,8 @@ check_format_info_main (format_check_results *res, location_t fmt_param_loc, tree format_string_cst, int format_length, tree params, unsigned HOST_WIDE_INT arg_num, - object_allocator &fwt_pool) + object_allocator &fwt_pool, + vec *arglocs) { const char * const orig_format_chars = format_chars; const tree first_fillin_param = params; @@ -2790,7 +2815,7 @@ check_format_info_main (format_check_results *res, argument_parser arg_parser (info, format_chars, format_string_cst, orig_format_chars, format_string_loc, flag_chars, has_operand_number, - first_fillin_param, fwt_pool); + first_fillin_param, fwt_pool, arglocs); if (!arg_parser.read_any_dollar ()) return; @@ -3020,7 +3045,8 @@ static void check_format_types (const substring_loc &fmt_loc, format_wanted_type *types, const format_kind_info *fki, int offset_to_type_start, - char conversion_char) + char conversion_char, + vec *arglocs) { for (; types != 0; types = types->next) { @@ -3060,11 +3086,19 @@ check_format_types (const substring_loc &fmt_loc, source_range param_range; source_range *param_range_ptr; - if (CAN_HAVE_LOCATION_P (cur_param)) + if (EXPR_HAS_LOCATION (cur_param)) { param_range = EXPR_LOCATION_RANGE (cur_param); param_range_ptr = ¶m_range; } + else if (arglocs) + { + /* arg_num is 1-based. */ + gcc_assert (types->arg_num > 0); + location_t param_loc = (*arglocs)[types->arg_num - 1]; + param_range = get_range_from_loc (line_table, param_loc); + param_range_ptr = ¶m_range; + } else param_range_ptr = NULL; @@ -3834,6 +3868,29 @@ init_dynamic_diag_info (void) local_tree_type_node = void_type_node; } + /* Similar to the above but for gcall*. */ + if (!local_gcall_ptr_node + || local_gcall_ptr_node == void_type_node) + { + if ((local_gcall_ptr_node = maybe_get_identifier ("gcall"))) + { + local_gcall_ptr_node + = identifier_global_value (local_gcall_ptr_node); + if (local_gcall_ptr_node) + { + if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL) + { + error ("% is not defined as a type"); + local_gcall_ptr_node = 0; + } + else + local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node); + } + } + else + local_gcall_ptr_node = void_type_node; + } + static tree hwi; if (!hwi) @@ -3976,24 +4033,6 @@ convert_format_name_to_system_name (const char *attr_name) return attr_name; } -/* Return true if TATTR_NAME and ATTR_NAME are the same format attribute, - counting "name" and "__name__" as the same, false otherwise. */ -static bool -cmp_attribs (const char *tattr_name, const char *attr_name) -{ - int alen = strlen (attr_name); - int slen = (tattr_name ? strlen (tattr_name) : 0); - if (alen > 4 && attr_name[0] == '_' && attr_name[1] == '_' - && attr_name[alen - 1] == '_' && attr_name[alen - 2] == '_') - { - attr_name += 2; - alen -= 4; - } - if (alen != slen || strncmp (tattr_name, attr_name, alen) != 0) - return false; - return true; -} - /* Handle a "format" attribute; arguments as in struct attribute_spec.handler. */ tree @@ -4022,6 +4061,10 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args, } #endif + /* Canonicalize name of format function. */ + if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE) + TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args)); + if (!decode_format_attr (args, &info, 0)) { *no_add_attrs = true; diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h index 37fa3828485a4..05e9bb73ef132 100644 --- a/gcc/c-family/c-format.h +++ b/gcc/c-family/c-format.h @@ -298,6 +298,7 @@ struct format_kind_info #define T_UC &unsigned_char_type_node #define T99_UC { STD_C99, NULL, T_UC } #define T_V &void_type_node +#define T89_G { STD_C89, NULL, &local_gcall_ptr_node } #define T89_T { STD_C89, NULL, &local_tree_type_node } #define T89_V { STD_C89, NULL, T_V } #define T_W &wchar_type_node diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index e1c8bdff98687..a614b266baf16 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -316,6 +316,7 @@ c_common_has_attribute (cpp_reader *pfile) { attr_name = get_identifier ((const char *) cpp_token_as_text (pfile, token)); + attr_name = canonicalize_attr_name (attr_name); if (c_dialect_cxx ()) { int idx = 0; @@ -987,7 +988,7 @@ interpret_float (const cpp_token *token, unsigned int flags, } if (type != const_type) - value = build1 (EXCESS_PRECISION_EXPR, type, value); + value = build1_loc (token->src_loc, EXCESS_PRECISION_EXPR, type, value); return value; } diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 977cb0ea15303..eef7ac0c769b5 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -181,6 +181,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, bool test) { tree x, type, addr, pre = NULL_TREE; + HOST_WIDE_INT bitpos = 0, bitsize = 0; if (lhs == error_mark_node || rhs == error_mark_node || v == error_mark_node || lhs1 == error_mark_node @@ -209,6 +210,29 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, opcode = TRUNC_DIV_EXPR; /* ??? Validate that rhs does not overlap lhs. */ + tree blhs = NULL; + if (TREE_CODE (lhs) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL + && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1)) + && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1))) + { + tree field = TREE_OPERAND (lhs, 1); + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field); + if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)) + && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr))) + bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field)) + - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT; + else + bitpos = 0; + bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)) + - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr))); + gcc_assert (tree_fits_shwi_p (DECL_SIZE (field))); + bitsize = tree_to_shwi (DECL_SIZE (field)); + blhs = lhs; + type = TREE_TYPE (repr); + lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0), + repr, TREE_OPERAND (lhs, 2)); + } /* Take and save the address of the lhs. From then on we'll reference it via indirection. */ @@ -228,13 +252,18 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, DECL_CONTEXT (var) = current_function_decl; addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL); } + tree orig_lhs = lhs; lhs = build_indirect_ref (loc, addr, RO_NULL); + tree new_lhs = lhs; if (code == OMP_ATOMIC_READ) { x = build1 (OMP_ATOMIC_READ, type, addr); SET_EXPR_LOCATION (x, loc); OMP_ATOMIC_SEQ_CST (x) = seq_cst; + if (blhs) + x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x, + bitsize_int (bitsize), bitsize_int (bitpos)); return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, loc, x, NULL_TREE); } @@ -242,14 +271,25 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, /* There are lots of warnings, errors, and conversions that need to happen in the course of interpreting a statement. Use the normal mechanisms to do this, and then take it apart again. */ - if (swapped) + if (blhs) { - rhs = build_binary_op (loc, opcode, rhs, lhs, 1); + lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs, + bitsize_int (bitsize), bitsize_int (bitpos)); + if (swapped) + rhs = build_binary_op (loc, opcode, rhs, lhs, true); + else if (opcode != NOP_EXPR) + rhs = build_binary_op (loc, opcode, lhs, rhs, true); + opcode = NOP_EXPR; + } + else if (swapped) + { + rhs = build_binary_op (loc, opcode, rhs, lhs, true); opcode = NOP_EXPR; } bool save = in_late_binary_op; in_late_binary_op = true; - x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE); + x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode, + loc, rhs, NULL_TREE); in_late_binary_op = save; if (x == error_mark_node) return error_mark_node; @@ -262,6 +302,10 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, gcc_assert (TREE_CODE (x) == MODIFY_EXPR); rhs = TREE_OPERAND (x, 1); + if (blhs) + rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs, + rhs, bitsize_int (bitpos)); + /* Punt the actual generation of atomic operations to common code. */ if (code == OMP_ATOMIC) type = void_type_node; @@ -273,8 +317,8 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, location, just diagnose different variables. */ if (rhs1 && VAR_P (rhs1) - && VAR_P (lhs) - && rhs1 != lhs + && VAR_P (orig_lhs) + && rhs1 != orig_lhs && !test) { if (code == OMP_ATOMIC) @@ -286,29 +330,57 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, return error_mark_node; } + if (lhs1 + && lhs1 != orig_lhs + && TREE_CODE (lhs1) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL + && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1)) + && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1))) + { + tree field = TREE_OPERAND (lhs1, 1); + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field); + lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0), + repr, TREE_OPERAND (lhs1, 2)); + } + if (rhs1 + && rhs1 != orig_lhs + && TREE_CODE (rhs1) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL + && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1)) + && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1))) + { + tree field = TREE_OPERAND (rhs1, 1); + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field); + rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0), + repr, TREE_OPERAND (rhs1, 2)); + } + if (code != OMP_ATOMIC) { /* Generally it is hard to prove lhs1 and lhs are the same memory location, just diagnose different variables. */ - if (lhs1 && VAR_P (lhs1) && VAR_P (lhs)) + if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs)) { - if (lhs1 != lhs && !test) + if (lhs1 != orig_lhs && !test) { error_at (loc, "%<#pragma omp atomic capture%> uses two " "different variables for memory"); return error_mark_node; } } + if (blhs) + x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x, + bitsize_int (bitsize), bitsize_int (bitpos)); x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, loc, x, NULL_TREE); - if (rhs1 && rhs1 != lhs) + if (rhs1 && rhs1 != orig_lhs) { tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false); if (rhs1addr == error_mark_node) return error_mark_node; x = omit_one_operand_loc (loc, type, x, rhs1addr); } - if (lhs1 && lhs1 != lhs) + if (lhs1 && lhs1 != orig_lhs) { tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false); if (lhs1addr == error_mark_node) @@ -323,7 +395,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, } } } - else if (rhs1 && rhs1 != lhs) + else if (rhs1 && rhs1 != orig_lhs) { tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false); if (rhs1addr == error_mark_node) diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 1657e7a4390ee..0b13a188c1b38 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -957,16 +957,18 @@ c_common_post_options (const char **pfilename) if (flag_extern_tls_init) { -#if !defined (ASM_OUTPUT_DEF) || !SUPPORTS_WEAK - /* Lazy TLS initialization for a variable in another TU requires - alias and weak reference support. */ - if (flag_extern_tls_init > 0) - sorry ("external TLS initialization functions not supported " - "on this target"); - flag_extern_tls_init = 0; -#else - flag_extern_tls_init = 1; -#endif + if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK) + { + /* Lazy TLS initialization for a variable in another TU requires + alias and weak reference support. */ + if (flag_extern_tls_init > 0) + sorry ("external TLS initialization functions not supported " + "on this target"); + + flag_extern_tls_init = 0; + } + else + flag_extern_tls_init = 1; } if (num_in_fnames > 1) diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 48b02b88bb5ce..3b49aefc6ffee 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -815,7 +815,7 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) } struct cl_option_handlers handlers; - set_default_handlers (&handlers); + set_default_handlers (&handlers, NULL); const char *arg = NULL; if (cl_options[option_index].flags & CL_JOINED) arg = option_string + 1 + cl_options[option_index].opt_len; diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index fdb7b41f592e1..b8b8f665ef35e 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "c-pretty-print.h" #include "diagnostic.h" #include "stor-layout.h" +#include "stringpool.h" #include "attribs.h" #include "intl.h" #include "tree-pretty-print.h" diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index 541b53009c2bb..b1386db9c2585 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -25,10 +25,12 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-common.h" #include "ubsan.h" #include "c-family/c-ubsan.h" -#include "asan.h" #include "stor-layout.h" #include "builtins.h" #include "gimplify.h" +#include "stringpool.h" +#include "attribs.h" +#include "asan.h" /* Instrument division by zero and INT_MIN / -1. If not instrumenting, return NULL_TREE. */ diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 505070e5586ab..9c3073444cf50 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "diagnostic.h" #include "intl.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" #include "gcc-rich-location.h" #include "gimplify.h" @@ -2457,34 +2459,44 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc, || body_loc_exp == next_loc_exp) return; - /* Find the macro map for the macro expansion BODY_LOC. */ - const line_map *map = linemap_lookup (line_table, body_loc); - const line_map_macro *macro_map = linemap_check_macro (map); - - /* Now see if the following token is coming from the same macro - expansion. If it is, it's a problem, because it should've been - parsed at this point. We only look at odd-numbered indexes - within the MACRO_MAP_LOCATIONS array, i.e. the spelling locations - of the tokens. */ - bool found_guard = false; - bool found_next = false; - for (unsigned int i = 1; - i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (macro_map); - i += 2) - { - if (MACRO_MAP_LOCATIONS (macro_map)[i] == next_loc_exp) - found_next = true; - if (MACRO_MAP_LOCATIONS (macro_map)[i] == guard_loc_exp) - found_guard = true; - } + /* Find the macro maps for the macro expansions. */ + const line_map *body_map = linemap_lookup (line_table, body_loc); + const line_map *next_map = linemap_lookup (line_table, next_loc); + const line_map *guard_map = linemap_lookup (line_table, guard_loc); + + /* Now see if the following token (after the body) is coming from the + same macro expansion. If it is, it might be a problem. */ + if (body_map != next_map) + return; /* The conditional itself must not come from the same expansion, because we don't want to warn about #define IF if (x) x++; y++ and similar. */ - if (!found_next || found_guard) + if (guard_map == body_map) return; + /* Handle the case where NEXT and BODY come from the same expansion while + GUARD doesn't, yet we shouldn't warn. E.g. + + #define GUARD if (...) + #define GUARD2 GUARD + + and in the definition of another macro: + + GUARD2 + foo (); + return 1; + */ + while (linemap_macro_expansion_map_p (guard_map)) + { + const line_map_macro *mm = linemap_check_macro (guard_map); + guard_loc_exp = MACRO_MAP_EXPANSION_POINT_LOCATION (mm); + guard_map = linemap_lookup (line_table, guard_loc_exp); + if (guard_map == body_map) + return; + } + if (warning_at (body_loc, OPT_Wmultistatement_macros, "macro expands to multiple statements")) inform (guard_loc, "some parts of macro expansion are not guarded by " diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index e0ad3ab10b87f..3435fe90ccace 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -579,6 +579,10 @@ Wformat-truncation= C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2) Warn about calls to snprintf and similar functions that truncate output. +Wif-not-aligned +C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning +Warn when the field in a struct is not aligned. + Wignored-qualifiers C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra) Warn whenever type qualifiers are ignored. @@ -710,6 +714,10 @@ Wnamespaces C++ ObjC++ Var(warn_namespaces) Warning Warn on namespace definition. +Wpacked-not-aligned +C ObjC C++ ObjC++ Var(warn_packed_not_aligned) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) +Warn when fields in a struct with the packed attribute are misaligned. + Wsized-deallocation C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra) Warn about missing sized deallocation functions. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index aff4866d91583..0cf7bd26167ea 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,8 +1,189 @@ +2017-08-24 David Malcolm + + * c-tree.h (c_expr::get_location) Use EXPR_HAS_LOCATION rather + than CAN_HAVE_LOCATION_P when determining whether to use the + location_t value within "value". + +2017-08-21 David Malcolm + + * c-parser.c (c_parser_expr_list): Use c_expr::get_location () + rather than peeking the location of the first token. + * c-tree.h (c_expr::get_location): New method. + +2017-08-21 David Malcolm + + * c-typeck.c (build_function_call_vec): Pass arg_loc to call + to check_function_arguments. + +2017-08-18 Marek Polacek + + * c-parser.c (c_parser_postfix_expression): Remove unused code. Update + commentary. + +2017-08-18 H.J. Lu + + PR c/53037 + * c-decl.c (merge_decls): Also merge DECL_WARN_IF_NOT_ALIGN. + (check_bitfield_type_and_width): Don't allow bit-field with + warn_if_not_aligned type. + +2017-08-14 Martin Sebor + + PR c/81117 + * c-objc-common.c (c_objc_common_init): Handle 'G'. + +2017-08-11 Marek Polacek + + PR c/81795 + * c-decl.c (pushtag): Only print inform if the warning was printed. + (grokdeclarator): Likewise. + +2017-08-10 David Malcolm + + * c-parser.c (c_parser_error): Rename to... + (c_parser_error_richloc): ...this, making static, and adding + "richloc" parameter, passing it to the c_parse_error call, + rather than calling c_parser_set_source_position_from_token. + (c_parser_error): Reintroduce, reimplementing in terms of the + above, converting return type from void to bool. + (class token_pair): New class. + (struct matching_paren_traits): New struct. + (matching_parens): New typedef. + (struct matching_brace_traits): New struct. + (matching_braces): New typedef. + (get_matching_symbol): New function. + (c_parser_require): Add param MATCHING_LOCATION, using it to + highlight matching "opening" tokens for missing "closing" tokens. + (c_parser_skip_until_found): Likewise. + (c_parser_static_assert_declaration_no_semi): Convert explicit + parsing of CPP_OPEN_PAREN and CPP_CLOSE_PAREN to use of + class matching_parens, so that the pertinent open parenthesis is + highlighted when there are problems locating the close + parenthesis. + (c_parser_struct_or_union_specifier): Likewise. + (c_parser_typeof_specifier): Likewise. + (c_parser_alignas_specifier): Likewise. + (c_parser_simple_asm_expr): Likewise. + (c_parser_braced_init): Likewise, for matching_braces. + (c_parser_paren_condition): Likewise, for matching_parens. + (c_parser_switch_statement): Likewise. + (c_parser_for_statement): Likewise. + (c_parser_asm_statement): Likewise. + (c_parser_asm_operands): Likewise. + (c_parser_cast_expression): Likewise. + (c_parser_sizeof_expression): Likewise. + (c_parser_alignof_expression): Likewise. + (c_parser_generic_selection): Likewise. + (c_parser_postfix_expression): Likewise for cases RID_VA_ARG, + RID_OFFSETOF, RID_TYPES_COMPATIBLE_P, RID_AT_SELECTOR, + RID_AT_PROTOCOL, RID_AT_ENCODE, reindenting as necessary. + In case CPP_OPEN_PAREN, pass loc_open_paren to the + c_parser_skip_until_found call. + (c_parser_objc_class_definition): Use class matching_parens as + above. + (c_parser_objc_method_decl): Likewise. + (c_parser_objc_try_catch_finally_statement): Likewise. + (c_parser_objc_synchronized_statement): Likewise. + (c_parser_objc_at_property_declaration): Likewise. + (c_parser_oacc_wait_list): Likewise. + (c_parser_omp_var_list_parens): Likewise. + (c_parser_omp_clause_collapse): Likewise. + (c_parser_omp_clause_default): Likewise. + (c_parser_omp_clause_if): Likewise. + (c_parser_omp_clause_num_threads): Likewise. + (c_parser_omp_clause_num_tasks): Likewise. + (c_parser_omp_clause_grainsize): Likewise. + (c_parser_omp_clause_priority): Likewise. + (c_parser_omp_clause_hint): Likewise. + (c_parser_omp_clause_defaultmap): Likewise. + (c_parser_oacc_single_int_clause): Likewise. + (c_parser_omp_clause_ordered): Likewise. + (c_parser_omp_clause_reduction): Likewise. + (c_parser_omp_clause_schedule): Likewise. + (c_parser_omp_clause_num_teams): Likewise. + (c_parser_omp_clause_thread_limit): Likewise. + (c_parser_omp_clause_aligned): Likewise. + (c_parser_omp_clause_linear): Likewise. + (c_parser_omp_clause_safelen): Likewise. + (c_parser_omp_clause_simdlen): Likewise. + (c_parser_omp_clause_depend): Likewise. + (c_parser_omp_clause_map): Likewise. + (c_parser_omp_clause_device): Likewise. + (c_parser_omp_clause_dist_schedule): Likewise. + (c_parser_omp_clause_proc_bind): Likewise. + (c_parser_omp_clause_uniform): Likewise. + (c_parser_omp_for_loop): Likewise. + (c_parser_cilk_clause_vectorlength): Likewise. + (c_parser_cilk_clause_linear): Likewise. + (c_parser_transaction_expression): Likewise. + * c-parser.h (c_parser_require): Add param matching_location with + default UNKNOWN_LOCATION. + (c_parser_error): Convert return type from void to bool. + (c_parser_skip_until_found): Add param matching_location with + default UNKNOWN_LOCATION. + +2017-08-09 Marek Polacek + + * c-decl.c (build_enumerator): Use true/false instead of 1/0. + * c-tree.h (build_external_ref): Update declaration. + * c-typeck.c (build_array_ref): Use true/false instead of 1/0. + (build_external_ref): Change the type of a parameter to bool. + (parser_build_binary_op): Use true/false instead of 1/0. + (pointer_diff): Likewise. + (build_modify_expr): Likewise. + (set_designator): Change the type of a parameter to bool. + (set_init_index): Use true/false instead of 1/0. + (set_init_label): Likewise. + (output_init_element): Change the type of a parameter to bool. + (output_pending_init_elements): Use true/false instead of 1/0. + (process_init_element): Likewise. + (build_binary_op): Change the type of a parameter to bool. + +2017-08-09 Marek Polacek + + PR c/81233 + * c-typeck.c (pedwarn_init): Make the function take a variable list. + Call emit_diagnostic_valist instead of pedwarn. + (convert_for_assignment): Unroll the PEDWARN_FOR_ASSIGNMENT macro. + Print the relevant types in diagnostics. + +2017-08-09 Marek Polacek + + PR c/81417 + * c-array-notation.c (fix_builtin_array_notation_fn): Update calls to + build_conditional_expr. + * c-parser.c (c_parser_conditional_expression): Create locations for + EXP1 and EXP2 from their source ranges. Pass the locations down to + build_conditional_expr. + * c-tree.h (build_conditional_expr): Update declaration. + * c-typeck.c (build_conditional_expr): Add location_t parameters. + For -Wsign-compare, also print the types. + +2017-08-08 Martin Liska + + * c-convert.c: Include header files. + * c-typeck.c: Likewise. + +2017-08-07 Martin Liska + + * c-parser.c (c_parser_attributes): Canonicalize name of an + attribute. + +2017-08-02 Marek Polacek + + PR c/81289 + * c-parser.c (c_parser_unary_expression): Use set_error. + + PR c/81448 + PR c/81306 + * c-warn.c (warn_for_multistatement_macros): Prevent bogus + warnings. Avoid walking MACRO_MAP_LOCATIONS. + 2017-07-31 Jan Hubicka Martin Liska * c-typeck.c (c_finish_goto_label): Build gimple predict - stament. + statement. 2017-07-31 Martin Liska diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c index e430f5c681bfd..40f1cfdabb82b 100644 --- a/gcc/c/c-array-notation.c +++ b/gcc/c/c-array-notation.c @@ -355,8 +355,9 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm, build_zero_cst (TREE_TYPE (func_parm))); new_expr = build_conditional_expr - (location, new_cond_expr, false, new_yes_expr, - TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr)); + (location, new_cond_expr, false, + new_yes_expr, TREE_TYPE (new_yes_expr), location, + new_no_expr, TREE_TYPE (new_no_expr), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO: new_var_init = build_modify_expr @@ -375,8 +376,9 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm, build_zero_cst (TREE_TYPE (func_parm))); new_expr = build_conditional_expr - (location, new_cond_expr, false, new_yes_expr, - TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr)); + (location, new_cond_expr, false, + new_yes_expr, TREE_TYPE (new_yes_expr), location, + new_no_expr, TREE_TYPE (new_no_expr), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO: new_var_init = build_modify_expr @@ -394,8 +396,9 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm, build_zero_cst (TREE_TYPE (func_parm))); new_expr = build_conditional_expr - (location, new_cond_expr, false, new_yes_expr, - TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr)); + (location, new_cond_expr, false, + new_yes_expr, TREE_TYPE (new_yes_expr), location, + new_no_expr, TREE_TYPE (new_no_expr), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO: new_var_init = build_modify_expr @@ -413,8 +416,9 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm, build_zero_cst (TREE_TYPE (func_parm))); new_expr = build_conditional_expr - (location, new_cond_expr, false, new_yes_expr, - TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr)); + (location, new_cond_expr, false, + new_yes_expr, TREE_TYPE (new_yes_expr), location, + new_no_expr, TREE_TYPE (new_no_expr), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX: if (TYPE_MIN_VALUE (new_var_type)) @@ -434,7 +438,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_expr = build_conditional_expr (location, build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false, - new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var)); + new_yes_expr, TREE_TYPE (*new_var), location, + new_no_expr, TREE_TYPE (*new_var), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN: if (TYPE_MAX_VALUE (new_var_type)) @@ -454,7 +459,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) new_expr = build_conditional_expr (location, build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false, - new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var)); + new_yes_expr, TREE_TYPE (*new_var), location, + new_no_expr, TREE_TYPE (*new_var), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND: new_var_init = build_modify_expr @@ -504,7 +510,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value, func_parm), false, - new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var)); + new_yes_list, TREE_TYPE (*new_var), location, + new_no_list, TREE_TYPE (*new_var), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND: new_var_init = build_modify_expr @@ -554,7 +561,8 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var) build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value, func_parm), false, - new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var)); + new_yes_list, TREE_TYPE (*new_var), location, + new_no_list, TREE_TYPE (*new_var), location); break; case BUILT_IN_CILKPLUS_SEC_REDUCE: new_var_init = build_modify_expr diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c index bc649178f4c5d..8752132d175bd 100644 --- a/gcc/c/c-convert.c +++ b/gcc/c/c-convert.c @@ -31,6 +31,8 @@ along with GCC; see the file COPYING3. If not see #include "convert.h" #include "langhooks.h" #include "ubsan.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" /* Change of width--truncation and extension of integers or reals-- diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index a54e121843422..d526f0e88e4e2 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -1557,11 +1557,10 @@ pushtag (location_t loc, tree name, tree type) && (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl)) != TYPE_MAIN_VARIANT (type))) { - warning_at (loc, OPT_Wc___compat, - ("using %qD as both a typedef and a tag is " - "invalid in C++"), - b->decl); - if (b->locus != UNKNOWN_LOCATION) + if (warning_at (loc, OPT_Wc___compat, + ("using %qD as both a typedef and a tag is " + "invalid in C++"), b->decl) + && b->locus != UNKNOWN_LOCATION) inform (b->locus, "originally defined here"); } } @@ -2384,6 +2383,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) SET_DECL_ALIGN (newdecl, DECL_ALIGN (olddecl)); DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); } + if (DECL_WARN_IF_NOT_ALIGN (olddecl) + > DECL_WARN_IF_NOT_ALIGN (newdecl)) + SET_DECL_WARN_IF_NOT_ALIGN (newdecl, + DECL_WARN_IF_NOT_ALIGN (olddecl)); } /* Keep the old rtl since we can safely use it. */ @@ -5396,6 +5399,13 @@ check_bitfield_type_and_width (location_t loc, tree *type, tree *width, *type = unsigned_type_node; } + if (TYPE_WARN_IF_NOT_ALIGN (*type)) + { + error_at (loc, "cannot declare bit-field %qs with % type", + name); + *type = unsigned_type_node; + } + type_mv = TYPE_MAIN_VARIANT (*type); if (!in_system_header_at (input_location) && type_mv != integer_type_node @@ -6596,11 +6606,10 @@ grokdeclarator (const struct c_declarator *declarator, || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b))) && TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type)) { - warning_at (declarator->id_loc, OPT_Wc___compat, - ("using %qD as both a typedef and a tag is " - "invalid in C++"), - decl); - if (b->locus != UNKNOWN_LOCATION) + if (warning_at (declarator->id_loc, OPT_Wc___compat, + ("using %qD as both a typedef and a tag is " + "invalid in C++"), decl) + && b->locus != UNKNOWN_LOCATION) inform (b->locus, "originally defined here"); } } @@ -8475,7 +8484,7 @@ build_enumerator (location_t decl_loc, location_t loc, /* Set basis for default for next value. */ the_enum->enum_next_value = build_binary_op (EXPR_LOC_OR_LOC (value, input_location), - PLUS_EXPR, value, integer_one_node, 0); + PLUS_EXPR, value, integer_one_node, false); the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value); /* Now create a declaration for the enum value name. */ diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c index 05212b2cb8e4c..8f4d3eb91c538 100644 --- a/gcc/c/c-objc-common.c +++ b/gcc/c/c-objc-common.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "c-family/c-pretty-print.h" #include "tree-pretty-print.h" +#include "gimple-pretty-print.h" #include "langhooks.h" #include "c-objc-common.h" @@ -66,6 +67,8 @@ c_objc_common_init (void) %D: a general decl, %E: an identifier or expression, %F: a function declaration, + %G: a Gimple call statement, + %K: a CALL_EXPR, %T: a type. %V: a list of type qualifiers from a tree. %v: an explicit list of type qualifiers @@ -87,9 +90,16 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec, if (precision != 0 || wide) return false; + if (*spec == 'G') + { + percent_G_format (text); + return true; + } + if (*spec == 'K') { - percent_K_format (text); + t = va_arg (*text->args_ptr, tree); + percent_K_format (text, t); return true; } diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 16cd357997291..3d15eb7a6de08 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -850,21 +850,26 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind, MESSAGE (specified by the caller) is usually of the form "expected OTHER-TOKEN". + Use RICHLOC as the location of the diagnostic. + Do not issue a diagnostic if still recovering from an error. + Return true iff an error was actually emitted. + ??? This is taken from the C++ parser, but building up messages in this way is not i18n-friendly and some other approach should be used. */ -void -c_parser_error (c_parser *parser, const char *gmsgid) +static bool +c_parser_error_richloc (c_parser *parser, const char *gmsgid, + rich_location *richloc) { c_token *token = c_parser_peek_token (parser); if (parser->error) - return; + return false; parser->error = true; if (!gmsgid) - return; + return false; /* If this is actually a conflict marker, report it as such. */ if (token->type == CPP_LSHIFT @@ -875,13 +880,10 @@ c_parser_error (c_parser *parser, const char *gmsgid) if (c_parser_peek_conflict_marker (parser, token->type, &loc)) { error_at (loc, "version control conflict marker in file"); - return; + return true; } } - /* This diagnostic makes more sense if it is tagged to the line of - the token we just peeked at. */ - c_parser_set_source_position_from_token (token); c_parse_error (gmsgid, /* Because c_parse_error does not understand CPP_KEYWORD, keywords are treated like @@ -891,18 +893,157 @@ c_parser_error (c_parser *parser, const char *gmsgid) token, we need to pass 0 here and we will not get the source spelling of some tokens but rather the canonical spelling. */ - token->value, /*flags=*/0); + token->value, /*flags=*/0, richloc); + return true; +} + +/* As c_parser_error_richloc, but issue the message at the + location of PARSER's next token, or at input_location + if the next token is EOF. */ + +bool +c_parser_error (c_parser *parser, const char *gmsgid) +{ + c_token *token = c_parser_peek_token (parser); + c_parser_set_source_position_from_token (token); + rich_location richloc (line_table, input_location); + return c_parser_error_richloc (parser, gmsgid, &richloc); +} + +/* Some tokens naturally come in pairs e.g.'(' and ')'. + This class is for tracking such a matching pair of symbols. + In particular, it tracks the location of the first token, + so that if the second token is missing, we can highlight the + location of the first token when notifying the user about the + problem. */ + +template +class token_pair +{ + public: + /* token_pair's ctor. */ + token_pair () : m_open_loc (UNKNOWN_LOCATION) {} + + /* If the next token is the opening symbol for this pair, consume it and + return true. + Otherwise, issue an error and return false. + In either case, record the location of the opening token. */ + + bool require_open (c_parser *parser) + { + c_token *token = c_parser_peek_token (parser); + if (token) + m_open_loc = token->location; + + return c_parser_require (parser, traits_t::open_token_type, + traits_t::open_gmsgid); + } + + /* Consume the next token from PARSER, recording its location as + that of the opening token within the pair. */ + + void consume_open (c_parser *parser) + { + c_token *token = c_parser_peek_token (parser); + gcc_assert (token->type == traits_t::open_token_type); + m_open_loc = token->location; + c_parser_consume_token (parser); + } + + /* If the next token is the closing symbol for this pair, consume it + and return true. + Otherwise, issue an error, highlighting the location of the + corresponding opening token, and return false. */ + + bool require_close (c_parser *parser) const + { + return c_parser_require (parser, traits_t::close_token_type, + traits_t::close_gmsgid, m_open_loc); + } + + /* Like token_pair::require_close, except that tokens will be skipped + until the desired token is found. An error message is still produced + if the next token is not as expected. */ + + void skip_until_found_close (c_parser *parser) const + { + c_parser_skip_until_found (parser, traits_t::close_token_type, + traits_t::close_gmsgid, m_open_loc); + } + + private: + location_t m_open_loc; +}; + +/* Traits for token_pair for tracking matching pairs of parentheses. */ + +struct matching_paren_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN; + static const char * const open_gmsgid; + static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN; + static const char * const close_gmsgid; +}; + +const char * const matching_paren_traits::open_gmsgid = "expected %<(%>"; +const char * const matching_paren_traits::close_gmsgid = "expected %<)%>"; + +/* "matching_parens" is a token_pair class for tracking matching + pairs of parentheses. */ + +typedef token_pair matching_parens; + +/* Traits for token_pair for tracking matching pairs of braces. */ + +struct matching_brace_traits +{ + static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE; + static const char * const open_gmsgid; + static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE; + static const char * const close_gmsgid; +}; + +const char * const matching_brace_traits::open_gmsgid = "expected %<{%>"; +const char * const matching_brace_traits::close_gmsgid = "expected %<}%>"; + +/* "matching_braces" is a token_pair class for tracking matching + pairs of braces. */ + +typedef token_pair matching_braces; + +/* Get a description of the matching symbol to TYPE e.g. "(" for + CPP_CLOSE_PAREN. */ + +static const char * +get_matching_symbol (enum cpp_ttype type) +{ + switch (type) + { + default: + gcc_unreachable (); + return ""; + case CPP_CLOSE_PAREN: + return "("; + case CPP_CLOSE_BRACE: + return "{"; + } } /* If the next token is of the indicated TYPE, consume it. Otherwise, issue the error MSGID. If MSGID is NULL then a message has already been produced and no message will be produced this time. Returns - true if found, false otherwise. */ + true if found, false otherwise. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TYPE is + CPP_CLOSE_PAREN). */ bool c_parser_require (c_parser *parser, enum cpp_ttype type, - const char *msgid) + const char *msgid, + location_t matching_location) { if (c_parser_next_token_is (parser, type)) { @@ -911,7 +1052,24 @@ c_parser_require (c_parser *parser, } else { - c_parser_error (parser, msgid); + location_t next_token_loc = c_parser_peek_token (parser)->location; + gcc_rich_location richloc (next_token_loc); + + /* If matching_location != UNKNOWN_LOCATION, highlight it. + Attempt to consolidate diagnostics by printing it as a + secondary range within the main diagnostic. */ + bool added_matching_location = false; + if (matching_location != UNKNOWN_LOCATION) + added_matching_location + = richloc.add_location_if_nearby (matching_location); + + if (c_parser_error_richloc (parser, msgid, &richloc)) + /* If we weren't able to consolidate matching_location, then + print it as a secondary diagnostic. */ + if (matching_location != UNKNOWN_LOCATION && !added_matching_location) + inform (matching_location, "to match this %qs", + get_matching_symbol (type)); + return false; } } @@ -940,16 +1098,22 @@ c_parser_require_keyword (c_parser *parser, desired token is found. An error message is still produced if the next token is not as expected. If MSGID is NULL then a message has already been produced and no message will be produced this - time. */ + time. + + If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it + within any error as the location of an "opening" token matching + the close token TYPE (e.g. the location of the '(' when TYPE is + CPP_CLOSE_PAREN). */ void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, - const char *msgid) + const char *msgid, + location_t matching_location) { unsigned nesting_depth = 0; - if (c_parser_require (parser, type, msgid)) + if (c_parser_require (parser, type, msgid, matching_location)) return; /* Skip tokens until the desired token is found. */ @@ -2210,7 +2374,8 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) pedwarn_c99 (assert_loc, OPT_Wpedantic, "ISO C90 does not support %<_Static_assert%>"); c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return; location_t value_tok_loc = c_parser_peek_token (parser)->location; value = c_parser_expr_no_commas (parser, NULL).value; @@ -2237,7 +2402,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) parser->lex_untranslated_string = false; return; } - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (value))) { @@ -2922,7 +3087,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) tree name; gcc_assert (c_dialect_objc ()); c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto end_at_defs; if (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME) @@ -2936,8 +3102,7 @@ c_parser_struct_or_union_specifier (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto end_at_defs; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); contents = nreverse (objc_get_class_ivars (name)); } end_at_defs: @@ -3224,7 +3389,8 @@ c_parser_typeof_specifier (c_parser *parser) c_parser_consume_token (parser); c_inhibit_evaluation_warnings++; in_typeof++; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { c_inhibit_evaluation_warnings--; in_typeof--; @@ -3265,7 +3431,7 @@ c_parser_typeof_specifier (c_parser *parser) if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec)) ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return ret; } @@ -3291,7 +3457,8 @@ c_parser_alignas_specifier (c_parser * parser) else pedwarn_c99 (loc, OPT_Wpedantic, "ISO C90 does not support %<_Alignas%>"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return ret; if (c_parser_next_tokens_start_typename (parser, cla_prefer_id)) { @@ -3302,7 +3469,7 @@ c_parser_alignas_specifier (c_parser * parser) } else ret = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return ret; } @@ -3953,14 +4120,15 @@ c_parser_simple_asm_expr (c_parser *parser) lex_untranslated_string kludge. */ parser->lex_untranslated_string = true; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { parser->lex_untranslated_string = false; return NULL_TREE; } str = c_parser_asm_string_literal (parser); parser->lex_untranslated_string = false; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; @@ -4170,9 +4338,11 @@ c_parser_attributes (c_parser *parser) attr_name = c_parser_attribute_any_word (parser); if (attr_name == NULL) break; + attr_name = canonicalize_attr_name (attr_name); if (is_cilkplus_vector_p (attr_name)) { c_token *v_token = c_parser_peek_token (parser); + v_token->value = canonicalize_attr_name (v_token->value); c_parser_cilk_simd_fn_vector_attrs (parser, *v_token); /* If the next token isn't a comma, we're done. */ if (!c_parser_next_token_is (parser, CPP_COMMA)) @@ -4236,6 +4406,7 @@ c_parser_attributes (c_parser *parser) release_tree_vector (expr_list); } } + attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) c_parser_consume_token (parser); @@ -4395,7 +4566,8 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, location_t brace_loc = c_parser_peek_token (parser)->location; gcc_obstack_init (&braced_init_obstack); gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); - c_parser_consume_token (parser); + matching_braces braces; + braces.consume_open (parser); if (nested_p) { finish_implicit_inits (brace_loc, outer_obstack); @@ -4433,7 +4605,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, ret.value = error_mark_node; ret.original_code = ERROR_MARK; ret.original_type = NULL; - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>"); + braces.skip_until_found_close (parser); pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma); obstack_free (&braced_init_obstack, NULL); return ret; @@ -5456,10 +5628,11 @@ static tree c_parser_paren_condition (c_parser *parser) { tree cond; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return error_mark_node; cond = c_parser_condition (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return cond; } @@ -5728,7 +5901,8 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) c_parser_consume_token (parser); block = c_begin_compound_stmt (flag_isoc99); bool explicit_cast_p = false; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { switch_cond_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) @@ -5743,7 +5917,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p) "%<_Cilk_spawn%> statement cannot be used as a condition for switch statement", switch_cond_loc)) expr = error_mark_node; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else { @@ -5953,7 +6127,8 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ()); cond = error_mark_node; incr = error_mark_node; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { /* Parse the initialization declaration or expression. */ object_expression = error_mark_node; @@ -6100,7 +6275,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p) incr = c_process_expr_stmt (loc, ce.value); } } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } save_break = c_break_label; c_break_label = NULL_TREE; @@ -6194,7 +6369,8 @@ c_parser_asm_statement (c_parser *parser) parser->lex_untranslated_string = true; ret = NULL; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto error; str = c_parser_asm_string_literal (parser); @@ -6252,7 +6428,7 @@ c_parser_asm_statement (c_parser *parser) } done_asm: - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto error; @@ -6317,7 +6493,8 @@ c_parser_asm_operands (c_parser *parser) if (str == NULL_TREE) return NULL_TREE; parser->lex_untranslated_string = false; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { parser->lex_untranslated_string = true; return NULL_TREE; @@ -6325,7 +6502,7 @@ c_parser_asm_operands (c_parser *parser) expr = c_parser_expression (parser); mark_exp_read (expr.value); parser->lex_untranslated_string = true; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; @@ -6508,7 +6685,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, tree omp_atomic_lhs) { struct c_expr cond, exp1, exp2, ret; - location_t start, cond_loc, colon_loc, middle_loc; + location_t start, cond_loc, colon_loc; gcc_assert (!after || c_dialect_objc ()); @@ -6527,7 +6704,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, { tree eptype = NULL_TREE; - middle_loc = c_parser_peek_token (parser)->location; + location_t middle_loc = c_parser_peek_token (parser)->location; pedwarn (middle_loc, OPT_Wpedantic, "ISO C forbids omitting the middle term of a ?: expression"); if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR) @@ -6544,6 +6721,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, if (eptype) exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value); exp1.original_type = NULL; + exp1.src_range = cond.src_range; cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value); c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node; } @@ -6575,10 +6753,12 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true); } c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; + location_t loc1 = make_location (exp1.get_start (), exp1.src_range); + location_t loc2 = make_location (exp2.get_start (), exp2.src_range); ret.value = build_conditional_expr (colon_loc, cond.value, cond.original_code == C_MAYBE_CONST_EXPR, - exp1.value, exp1.original_type, - exp2.value, exp2.original_type); + exp1.value, exp1.original_type, loc1, + exp2.value, exp2.original_type, loc2); ret.original_code = ERROR_MARK; if (exp1.value == error_mark_node || exp2.value == error_mark_node) ret.original_type = NULL; @@ -6934,9 +7114,10 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) struct c_type_name *type_name; struct c_expr ret; struct c_expr expr; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (type_name == NULL) { ret.value = error_mark_node; @@ -7099,9 +7280,9 @@ c_parser_unary_expression (c_parser *parser) else { c_parser_error (parser, "expected identifier"); - ret.value = error_mark_node; + ret.set_error (); } - return ret; + return ret; case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) { @@ -7163,10 +7344,11 @@ c_parser_sizeof_expression (c_parser *parser) /* Either sizeof ( type-name ) or sizeof unary-expression starting with a compound literal. */ struct c_type_name *type_name; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); expr_loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); finish = parser->tokens_buf[0].location; if (type_name == NULL) { @@ -7245,11 +7427,12 @@ c_parser_alignof_expression (c_parser *parser) location_t loc; struct c_type_name *type_name; struct c_expr ret; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); end_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (type_name == NULL) { struct c_expr ret; @@ -7408,7 +7591,8 @@ c_parser_generic_selection (c_parser *parser) pedwarn_c99 (generic_loc, OPT_Wpedantic, "ISO C90 does not support %<_Generic%>"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return error_expr; c_inhibit_evaluation_warnings++; @@ -7550,7 +7734,7 @@ c_parser_generic_selection (c_parser *parser) c_parser_consume_token (parser); } - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return error_expr; @@ -7568,7 +7752,8 @@ c_parser_generic_selection (c_parser *parser) } /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2, - C11 6.5.1-6.5.2). + C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to + call c_parser_postfix_expression_after_paren_type on encountering them. postfix-expression: primary-expression @@ -7608,7 +7793,7 @@ c_parser_generic_selection (c_parser *parser) __builtin_types_compatible_p ( type-name , type-name ) __builtin_complex ( assignment-expression , assignment-expression ) __builtin_shuffle ( assignment-expression , assignment-expression ) - __builtin_shuffle ( assignment-expression , + __builtin_shuffle ( assignment-expression , assignment-expression , assignment-expression, ) @@ -7759,28 +7944,6 @@ c_parser_postfix_expression (c_parser *parser) set_c_expr_source_range (&expr, loc, close_loc); mark_exp_read (expr.value); } - else if (c_token_starts_typename (c_parser_peek_2nd_token (parser))) - { - /* A compound literal. ??? Can we actually get here rather - than going directly to - c_parser_postfix_expression_after_paren_type from - elsewhere? */ - location_t loc; - struct c_type_name *type_name; - c_parser_consume_token (parser); - loc = c_parser_peek_token (parser)->location; - type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - if (type_name == NULL) - { - expr.set_error (); - } - else - expr = c_parser_postfix_expression_after_paren_type (parser, - type_name, - loc); - } else { /* A parenthesized expression. */ @@ -7796,7 +7959,7 @@ c_parser_postfix_expression (c_parser *parser) location_t loc_close_paren = c_parser_peek_token (parser)->location; set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + "expected %<)%>", loc_open_paren); } break; case CPP_KEYWORD: @@ -7833,7 +7996,8 @@ c_parser_postfix_expression (c_parser *parser) { location_t start_loc = loc; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) { expr.set_error (); break; @@ -7873,25 +8037,25 @@ c_parser_postfix_expression (c_parser *parser) } break; case RID_OFFSETOF: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - parser->error = true; - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - gcc_assert (parser->error); - if (parser->error) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } - { + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + parser->error = true; + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + gcc_assert (parser->error); + if (parser->error) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } tree type = groktypename (t1, NULL, NULL); tree offsetof_ref; if (type == error_mark_node) @@ -8008,34 +8172,34 @@ c_parser_postfix_expression (c_parser *parser) break; } case RID_TYPES_COMPATIBLE_P: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.set_error (); - break; - } - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } - t2 = c_parser_type_name (parser); - if (t2 == NULL) - { - expr.set_error (); - break; - } { + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.set_error (); + break; + } + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } + t2 = c_parser_type_name (parser); + if (t2 == NULL) + { + expr.set_error (); + break; + } location_t close_paren_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); tree e1, e2; e1 = groktypename (t1, NULL, NULL); e2 = groktypename (t2, NULL, NULL); @@ -8201,67 +8365,67 @@ c_parser_postfix_expression (c_parser *parser) break; } case RID_AT_SELECTOR: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } { + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } tree sel = c_parser_objc_selector_arg (parser); location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); expr.value = objc_build_selector_expr (loc, sel); set_c_expr_source_range (&expr, loc, close_loc); } break; case RID_AT_PROTOCOL: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.set_error (); - break; - } { + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.set_error (); + break; + } tree id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); expr.value = objc_build_protocol_expr (id); set_c_expr_source_range (&expr, loc, close_loc); } break; case RID_AT_ENCODE: - /* Extension to support C-structures in the archiver. */ - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.set_error (); - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.set_error (); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; - } { + /* Extension to support C-structures in the archiver. */ + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + matching_parens parens; + if (!parens.require_open (parser)) + { + expr.set_error (); + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.set_error (); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } location_t close_loc = c_parser_peek_token (parser)->location; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); + parens.skip_until_found_close (parser); tree type = groktypename (t1, NULL, NULL); expr.value = objc_build_encode_expr (type); set_c_expr_source_range (&expr, loc, close_loc); @@ -8748,7 +8912,6 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, vec *ret; vec *orig_types; struct c_expr expr; - location_t loc = c_parser_peek_token (parser)->location; unsigned int idx = 0; ret = make_tree_vector (); @@ -8761,14 +8924,14 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, c_parser_check_literal_zero (parser, literal_zero_mask, 0); expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = convert_lvalue_to_rvalue (loc, expr, true, true); + expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); ret->quick_push (expr.value); if (orig_types) orig_types->quick_push (expr.original_type); if (locations) - locations->safe_push (loc); + locations->safe_push (expr.get_location ()); if (sizeof_arg != NULL && expr.original_code == SIZEOF_EXPR) { @@ -8778,19 +8941,19 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, while (c_parser_next_token_is (parser, CPP_COMMA)) { c_parser_consume_token (parser); - loc = c_parser_peek_token (parser)->location; if (literal_zero_mask) c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1); expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = convert_lvalue_to_rvalue (loc, expr, true, true); + expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, + true); if (fold_p) expr.value = c_fully_fold (expr.value, false, NULL); vec_safe_push (ret, expr.value); if (orig_types) vec_safe_push (orig_types, expr.original_type); if (locations) - locations->safe_push (loc); + locations->safe_push (expr.get_location ()); if (++idx < 3 && sizeof_arg != NULL && expr.original_code == SIZEOF_EXPR) @@ -8854,7 +9017,8 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) /* We have a category or class extension. */ tree id2; tree proto = NULL_TREE; - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -8874,7 +9038,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes) id2 = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!iface_p) { objc_start_category_implementation (id1, id2); @@ -9408,9 +9572,10 @@ c_parser_objc_method_decl (c_parser *parser, bool is_class_method, *attributes = NULL_TREE; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); type = c_parser_objc_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } sel = c_parser_objc_selector (parser); /* If there is no selector, or a colon follows, we have an @@ -9616,7 +9781,8 @@ c_parser_objc_try_catch_finally_statement (c_parser *parser) bool seen_open_paren = false; c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) seen_open_paren = true; if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) { @@ -9639,7 +9805,7 @@ c_parser_objc_try_catch_finally_statement (c_parser *parser) parameter_declaration = grokparm (parm, NULL); } if (seen_open_paren) - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); else { /* If there was no open parenthesis, we are recovering from @@ -9688,13 +9854,14 @@ c_parser_objc_synchronized_statement (c_parser *parser) c_parser_consume_token (parser); loc = c_parser_peek_token (parser)->location; objc_maybe_warn_exceptions (loc); - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { struct c_expr ce = c_parser_expression (parser); ce = convert_lvalue_to_rvalue (loc, ce, false, false); expr = ce.value; expr = c_fully_fold (expr, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else expr = error_mark_node; @@ -9988,9 +10155,11 @@ c_parser_objc_at_property_declaration (c_parser *parser) /* Parse the optional attribute list... */ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { + matching_parens parens; + /* Eat the '(' */ - c_parser_consume_token (parser); - + parens.consume_open (parser); + /* Property attribute keywords are valid now. */ parser->objc_property_attr_context = true; @@ -10078,7 +10247,7 @@ c_parser_objc_at_property_declaration (c_parser *parser) break; } parser->objc_property_attr_context = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } /* ... and the property declaration(s). */ properties = c_parser_struct_declaration (parser); @@ -10738,7 +10907,8 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) vec *args; tree t, args_tree; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL); @@ -10775,7 +10945,7 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) } release_tree_vector (args); - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); return list; } @@ -10933,10 +11103,11 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { list = c_parser_omp_variable_list (parser, loc, kind, list); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -11073,10 +11244,11 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list) check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile"); loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { num = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } if (num == error_mark_node) return list; @@ -11128,7 +11300,8 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc) location_t loc = c_parser_peek_token (parser)->location; tree c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -11168,7 +11341,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc) else c_parser_error (parser, "expected % or %"); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) return list; @@ -11231,7 +11404,8 @@ c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) location_t location = c_parser_peek_token (parser)->location; enum tree_code if_modifier = ERROR_MARK; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (is_omp && c_parser_next_token_is (parser, CPP_NAME)) @@ -11312,7 +11486,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp) } tree t = c_parser_condition (parser), c; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); for (c = list; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF) @@ -11411,7 +11585,8 @@ static tree c_parser_omp_clause_num_threads (c_parser *parser, tree list) { location_t num_threads_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11419,7 +11594,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11456,7 +11631,8 @@ static tree c_parser_omp_clause_num_tasks (c_parser *parser, tree list) { location_t num_tasks_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11464,7 +11640,7 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11501,7 +11677,8 @@ static tree c_parser_omp_clause_grainsize (c_parser *parser, tree list) { location_t grainsize_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11509,7 +11686,7 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11546,7 +11723,8 @@ static tree c_parser_omp_clause_priority (c_parser *parser, tree list) { location_t priority_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11554,7 +11732,7 @@ c_parser_omp_clause_priority (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11592,7 +11770,8 @@ static tree c_parser_omp_clause_hint (c_parser *parser, tree list) { location_t hint_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -11600,7 +11779,7 @@ c_parser_omp_clause_hint (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -11629,7 +11808,8 @@ c_parser_omp_clause_defaultmap (c_parser *parser, tree list) tree c; const char *p; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!c_parser_next_token_is (parser, CPP_NAME)) { @@ -11657,14 +11837,14 @@ c_parser_omp_clause_defaultmap (c_parser *parser, tree list) goto out_err; } c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap"); c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP); OMP_CLAUSE_CHAIN (c) = list; return c; out_err: - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -11701,7 +11881,8 @@ c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code, { location_t loc = c_parser_peek_token (parser)->location; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -11710,7 +11891,7 @@ c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code, tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == error_mark_node) return list; @@ -12040,9 +12221,10 @@ c_parser_omp_clause_ordered (c_parser *parser, tree list) location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { - c_parser_consume_token (parser); + matching_parens parens; + parens.consume_open (parser); num = c_parser_expr_no_commas (parser, NULL).value; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } if (num == error_mark_node) return list; @@ -12096,7 +12278,8 @@ static tree c_parser_omp_clause_reduction (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { enum tree_code code = ERROR_MARK; tree reduc_id = NULL_TREE; @@ -12194,7 +12377,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list) list = nl; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -12222,7 +12405,8 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) location_t loc = c_parser_peek_token (parser)->location; int modifiers = 0, nmodifiers = 0; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE); @@ -12333,7 +12517,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) else c_parser_error (parser, "expected integer expression"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, @@ -12446,7 +12630,8 @@ static tree c_parser_omp_clause_num_teams (c_parser *parser, tree list) { location_t num_teams_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -12454,7 +12639,7 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -12490,7 +12675,8 @@ static tree c_parser_omp_clause_thread_limit (c_parser *parser, tree list) { location_t num_thread_limit_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expression (parser); @@ -12498,7 +12684,7 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -12538,7 +12724,8 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; nl = c_parser_omp_variable_list (parser, clause_loc, @@ -12565,7 +12752,7 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list) OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -12584,7 +12771,8 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) tree nl, c, step; enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!is_cilk_simd_fn @@ -12607,7 +12795,7 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) OMP_CLAUSE_LINEAR, list); if (kind != OMP_CLAUSE_LINEAR_DEFAULT) - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -12639,7 +12827,7 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn) OMP_CLAUSE_LINEAR_KIND (c) = kind; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -12652,7 +12840,8 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree c, t; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -12669,7 +12858,7 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list) t = NULL_TREE; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == NULL_TREE || t == error_mark_node) return list; @@ -12690,7 +12879,8 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) location_t clause_loc = c_parser_peek_token (parser)->location; tree c, t; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; location_t expr_loc = c_parser_peek_token (parser)->location; @@ -12707,7 +12897,7 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) t = NULL_TREE; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (t == NULL_TREE || t == error_mark_node) return list; @@ -12819,7 +13009,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -12849,7 +13040,7 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) OMP_CLAUSE_DEPEND_KIND (c) = kind; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return c; } @@ -12867,13 +13058,13 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) OMP_CLAUSE_DEPEND_KIND (c) = kind; } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; invalid_kind: c_parser_error (parser, "invalid depend kind"); resync_fail: - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -12901,7 +13092,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list) tree always_id = NULL_TREE; tree nl, c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -12968,7 +13160,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) if (always_id_kind != C_ID_ID) { c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -12988,7 +13180,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) } if (always == 1) { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } } @@ -12998,7 +13190,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list) for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_SET_MAP_KIND (c, kind); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return nl; } @@ -13009,7 +13201,8 @@ static tree c_parser_omp_clause_device (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { location_t expr_loc = c_parser_peek_token (parser)->location; c_expr expr = c_parser_expr_no_commas (parser, NULL); @@ -13017,7 +13210,7 @@ c_parser_omp_clause_device (c_parser *parser, tree list) tree c, t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) { @@ -13046,7 +13239,8 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) tree c, t = NULL_TREE; location_t loc = c_parser_peek_token (parser)->location; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (!c_parser_next_token_is_keyword (parser, RID_STATIC)) @@ -13067,7 +13261,7 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); t = expr.value; t = c_fully_fold (t, false, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } else c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, @@ -13096,7 +13290,8 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) enum omp_clause_proc_bind_kind kind; tree c; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return list; if (c_parser_next_token_is (parser, CPP_NAME)) @@ -13115,7 +13310,7 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) goto invalid_kind; c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND); OMP_CLAUSE_PROC_BIND_KIND (c) = kind; OMP_CLAUSE_CHAIN (c) = list; @@ -13123,7 +13318,7 @@ c_parser_omp_clause_proc_bind (c_parser *parser, tree list) invalid_kind: c_parser_error (parser, "invalid proc_bind kind"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return list; } @@ -13154,11 +13349,12 @@ c_parser_omp_clause_uniform (c_parser *parser, tree list) /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM, list); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); } return list; } @@ -14951,7 +15147,8 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, { int bracecount = 0; - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) goto pop_scopes; /* Parse the initialization declaration or expression. */ @@ -15058,7 +15255,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, incr = c_process_expr_stmt (incr_loc, c_parser_expression (parser).value); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); if (decl == NULL || decl == error_mark_node || init == error_mark_node) fail = true; @@ -17565,7 +17762,8 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, clause. Represent it in OpenMP terms. */ check_no_duplicate_clause (clauses, OMP_CLAUSE_SAFELEN, "vectorlength"); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return clauses; location_t loc = c_parser_peek_token (parser)->location; @@ -17601,7 +17799,7 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, } } - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.require_close (parser); return clauses; } @@ -17623,7 +17821,8 @@ c_parser_cilk_clause_vectorlength (c_parser *parser, tree clauses, static tree c_parser_cilk_clause_linear (c_parser *parser, tree clauses) { - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (!parens.require_open (parser)) return clauses; location_t loc = c_parser_peek_token (parser)->location; @@ -17685,7 +17884,7 @@ c_parser_cilk_clause_linear (c_parser *parser, tree clauses) c_parser_consume_token (parser); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + parens.skip_until_found_close (parser); return clauses; } @@ -18049,7 +18248,8 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword) } parser->in_transaction = this_in; - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + matching_parens parens; + if (parens.require_open (parser)) { tree expr = c_parser_expression (parser).value; ret.original_type = TREE_TYPE (expr); @@ -18058,7 +18258,7 @@ c_parser_transaction_expression (c_parser *parser, enum rid keyword) TRANSACTION_EXPR_RELAXED (ret.value) = 1; SET_EXPR_LOCATION (ret.value, loc); ret.original_code = TRANSACTION_EXPR; - if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + if (!parens.require_close (parser)) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); goto error; diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h index 1e344c40e27d9..01a7b724081ab 100644 --- a/gcc/c/c-parser.h +++ b/gcc/c/c-parser.h @@ -136,11 +136,13 @@ extern c_token * c_parser_peek_token (c_parser *parser); extern c_token * c_parser_peek_2nd_token (c_parser *parser); extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n); extern bool c_parser_require (c_parser *parser, enum cpp_ttype type, - const char *msgid); -extern void c_parser_error (c_parser *parser, const char *gmsgid); + const char *msgid, + location_t matching_location = UNKNOWN_LOCATION); +extern bool c_parser_error (c_parser *parser, const char *gmsgid); extern void c_parser_consume_token (c_parser *parser); extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, - const char *msgid); + const char *msgid, + location_t = UNKNOWN_LOCATION); extern bool c_parser_next_token_starts_declspecs (c_parser *parser); bool c_parser_next_tokens_start_declaration (c_parser *parser); bool c_token_starts_typename (c_token *token); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index a8197eb768daf..96c7ae7613ff5 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -147,6 +147,14 @@ struct c_expr location_t get_start () const { return src_range.m_start; } location_t get_finish () const { return src_range.m_finish; } + location_t get_location () const + { + if (EXPR_HAS_LOCATION (value)) + return EXPR_LOCATION (value); + else + return make_location (get_start (), get_start (), get_finish ()); + } + /* Set the value to error_mark_node whilst ensuring that src_range is initialized. */ void set_error () @@ -634,7 +642,7 @@ extern void mark_exp_read (tree); extern tree composite_type (tree, tree); extern tree build_component_ref (location_t, tree, tree, location_t); extern tree build_array_ref (location_t, tree, tree); -extern tree build_external_ref (location_t, tree, int, tree *); +extern tree build_external_ref (location_t, tree, bool, tree *); extern void pop_maybe_used (bool); extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr); extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *); @@ -644,7 +652,7 @@ extern struct c_expr parser_build_binary_op (location_t, enum tree_code, struct c_expr, struct c_expr); extern tree build_conditional_expr (location_t, tree, bool, tree, tree, - tree, tree); + location_t, tree, tree, location_t); extern tree build_compound_expr (location_t, tree, tree); extern tree c_cast_expr (location_t, struct c_type_name *, tree); extern tree build_c_cast (location_t, tree, tree); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 71d0135018619..d7ca14801b936 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -50,6 +50,8 @@ along with GCC; see the file COPYING3. If not see #include "gomp-constants.h" #include "spellcheck-tree.h" #include "gcc-rich-location.h" +#include "stringpool.h" +#include "attribs.h" #include "asan.h" /* Possible cases of implicit bad conversions. Used to select @@ -104,10 +106,10 @@ static int spelling_length (void); static char *print_spelling (char *); static void warning_init (location_t, int, const char *); static tree digest_init (location_t, tree, tree, tree, bool, bool, int); -static void output_init_element (location_t, tree, tree, bool, tree, tree, int, +static void output_init_element (location_t, tree, tree, bool, tree, tree, bool, bool, struct obstack *); static void output_pending_init_elements (int, struct obstack *); -static bool set_designator (location_t, int, struct obstack *); +static bool set_designator (location_t, bool, struct obstack *); static void push_range_stack (tree, struct obstack *); static void add_pending_init (location_t, tree, tree, tree, bool, struct obstack *); @@ -2721,7 +2723,7 @@ build_array_ref (location_t loc, tree array, tree index) gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE); ret = build_indirect_ref (loc, build_binary_op (loc, PLUS_EXPR, ar, - index, 0), + index, false), RO_ARRAY_INDEXING); if (non_lvalue) ret = non_lvalue_loc (loc, ret); @@ -2736,7 +2738,7 @@ build_array_ref (location_t loc, tree array, tree index) for CONST_DECLs defined as enum constants. If the type of the identifier is not available, *TYPE is set to NULL. */ tree -build_external_ref (location_t loc, tree id, int fun, tree *type) +build_external_ref (location_t loc, tree id, bool fun, tree *type) { tree ref; tree decl = lookup_name (id); @@ -3116,7 +3118,7 @@ build_function_call_vec (location_t loc, vec arg_loc, /* Check that the arguments to the function are valid. */ bool warned_p = check_function_arguments (loc, fundecl, fntype, - nargs, argarray); + nargs, argarray, &arg_loc); if (name != NULL_TREE && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10)) @@ -3640,7 +3642,7 @@ parser_build_binary_op (location_t location, enum tree_code code, : TREE_TYPE (arg2.value)); result.value = build_binary_op (location, code, - arg1.value, arg2.value, 1); + arg1.value, arg2.value, true); result.original_code = code; result.original_type = NULL; @@ -3829,7 +3831,7 @@ pointer_diff (location_t loc, tree op0, tree op1) op0 = build_binary_op (loc, MINUS_EXPR, convert (inttype, op0), - convert (inttype, op1), 0); + convert (inttype, op1), false); /* This generates an error if op1 is pointer to incomplete type. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error_at (loc, "arithmetic on pointer to an incomplete type"); @@ -4096,7 +4098,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, add_stmt (loop_label); /* newval = old + val; */ - rhs = build_binary_op (loc, modifycode, old, val, 1); + rhs = build_binary_op (loc, modifycode, old, val, true); rhs = c_fully_fold (rhs, false, NULL); rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type, rhs, NULL_TREE, ic_assign, false, NULL_TREE, @@ -4863,8 +4865,8 @@ ep_convert_and_check (location_t loc, tree type, tree expr, tree build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, - tree op1, tree op1_original_type, tree op2, - tree op2_original_type) + tree op1, tree op1_original_type, location_t op1_loc, + tree op2, tree op2_original_type, location_t op2_loc) { tree type1; tree type2; @@ -5029,10 +5031,18 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, || (unsigned_op1 && tree_expr_nonnegative_warnv_p (op2, &ovf))) /* OK */; + else if (unsigned_op2) + warning_at (op1_loc, OPT_Wsign_compare, + "operand of ?: changes signedness from " + "%qT to %qT due to unsignedness of other " + "operand", TREE_TYPE (orig_op1), + TREE_TYPE (orig_op2)); else - warning_at (colon_loc, OPT_Wsign_compare, - ("signed and unsigned type in " - "conditional expression")); + warning_at (op2_loc, OPT_Wsign_compare, + "operand of ?: changes signedness from " + "%qT to %qT due to unsignedness of other " + "operand", TREE_TYPE (orig_op2), + TREE_TYPE (orig_op1)); } if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST) op1 = c_wrap_maybe_const (op1, !op1_maybe_const); @@ -5786,7 +5796,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, rhseval = newrhs; } newrhs = build_binary_op (location, - modifycode, lhs, newrhs, 1); + modifycode, lhs, newrhs, true); /* The original type of the right hand side is no longer meaningful. */ @@ -6055,20 +6065,19 @@ error_init (location_t loc, const char *gmsgid) it is unconditionally given. GMSGID identifies the message. The component name is taken from the spelling stack. */ -static void -pedwarn_init (location_t loc, int opt, const char *gmsgid) +static void ATTRIBUTE_GCC_DIAG (3,0) +pedwarn_init (location_t loc, int opt, const char *gmsgid, ...) { - char *ofwhat; - bool warned; - /* Use the location where a macro was expanded rather than where it was defined to make sure macros defined in system headers but used incorrectly elsewhere are diagnosed. */ source_location exploc = expansion_point_location_if_in_system_header (loc); - /* The gmsgid may be a format string with %< and %>. */ - warned = pedwarn (exploc, opt, gmsgid); - ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); + va_list ap; + va_start (ap, gmsgid); + bool warned = emit_diagnostic_valist (DK_PEDWARN, exploc, opt, gmsgid, &ap); + va_end (ap); + char *ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat && warned) inform (exploc, "(near initialization for %qs)", ofwhat); } @@ -6301,17 +6310,33 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (checktype != error_mark_node && TREE_CODE (type) == ENUMERAL_TYPE && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type)) - { - PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat, - G_("enum conversion when passing argument " - "%d of %qE is invalid in C++"), - G_("enum conversion in assignment is " - "invalid in C++"), - G_("enum conversion in initialization is " - "invalid in C++"), - G_("enum conversion in return is " - "invalid in C++")); - } + switch (errtype) + { + case ic_argpass: + if (pedwarn (expr_loc, OPT_Wc___compat, "enum conversion when " + "passing argument %d of %qE is invalid in C++", + parmnum, rname)) + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, + "expected %qT but argument is of type %qT", + type, rhstype); + break; + case ic_assign: + pedwarn (location, OPT_Wc___compat, "enum conversion from %qT to " + "%qT in assignment is invalid in C++", rhstype, type); + break; + case ic_init: + pedwarn_init (location, OPT_Wc___compat, "enum conversion from " + "%qT to %qT in initialization is invalid in C++", + rhstype, type); + break; + case ic_return: + pedwarn (location, OPT_Wc___compat, "enum conversion from %qT to " + "%qT in return is invalid in C++", rhstype, type); + break; + default: + gcc_unreachable (); + } } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) @@ -6717,15 +6742,36 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ; /* If there is a mismatch, do warn. */ else if (warn_pointer_sign) - PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign, - G_("pointer targets in passing argument " - "%d of %qE differ in signedness"), - G_("pointer targets in assignment " - "differ in signedness"), - G_("pointer targets in initialization " - "differ in signedness"), - G_("pointer targets in return differ " - "in signedness")); + switch (errtype) + { + case ic_argpass: + if (pedwarn (expr_loc, OPT_Wpointer_sign, + "pointer targets in passing argument %d of " + "%qE differ in signedness", parmnum, rname)) + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, + "expected %qT but argument is of type %qT", + type, rhstype); + break; + case ic_assign: + pedwarn (location, OPT_Wpointer_sign, + "pointer targets in assignment from %qT to %qT " + "differ in signedness", rhstype, type); + break; + case ic_init: + pedwarn_init (location, OPT_Wpointer_sign, + "pointer targets in initialization of %qT " + "from %qT differ in signedness", type, + rhstype); + break; + case ic_return: + pedwarn (location, OPT_Wpointer_sign, "pointer targets in " + "returning %qT from a function with return type " + "%qT differ in signedness", rhstype, type); + break; + default: + gcc_unreachable (); + } } else if (TREE_CODE (ttl) == FUNCTION_TYPE && TREE_CODE (ttr) == FUNCTION_TYPE) @@ -6750,17 +6796,39 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr)); } } - else - /* Avoid warning about the volatile ObjC EH puts on decls. */ - if (!objc_ok) - PEDWARN_FOR_ASSIGNMENT (location, expr_loc, - OPT_Wincompatible_pointer_types, - G_("passing argument %d of %qE from " - "incompatible pointer type"), - G_("assignment from incompatible pointer type"), - G_("initialization from incompatible " - "pointer type"), - G_("return from incompatible pointer type")); + /* Avoid warning about the volatile ObjC EH puts on decls. */ + else if (!objc_ok) + { + switch (errtype) + { + case ic_argpass: + if (pedwarn (expr_loc, OPT_Wincompatible_pointer_types, + "passing argument %d of %qE from incompatible " + "pointer type", parmnum, rname)) + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, + "expected %qT but argument is of type %qT", + type, rhstype); + break; + case ic_assign: + pedwarn (location, OPT_Wincompatible_pointer_types, + "assignment to %qT from incompatible pointer type %qT", + type, rhstype); + break; + case ic_init: + pedwarn_init (location, OPT_Wincompatible_pointer_types, + "initialization of %qT from incompatible pointer " + "type %qT", type, rhstype); + break; + case ic_return: + pedwarn (location, OPT_Wincompatible_pointer_types, + "returning %qT from a function with incompatible " + "return type %qT", rhstype, type); + break; + default: + gcc_unreachable (); + } + } return convert (type, rhs); } @@ -6777,31 +6845,70 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, or one that results from arithmetic, even including a cast to integer type. */ if (!null_pointer_constant) - PEDWARN_FOR_ASSIGNMENT (location, expr_loc, - OPT_Wint_conversion, - G_("passing argument %d of %qE makes " - "pointer from integer without a cast"), - G_("assignment makes pointer from integer " - "without a cast"), - G_("initialization makes pointer from " - "integer without a cast"), - G_("return makes pointer from integer " - "without a cast")); + switch (errtype) + { + case ic_argpass: + if (pedwarn (expr_loc, OPT_Wint_conversion, + "passing argument %d of %qE makes pointer from " + "integer without a cast", parmnum, rname)) + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, + "expected %qT but argument is of type %qT", + type, rhstype); + break; + case ic_assign: + pedwarn (location, OPT_Wint_conversion, + "assignment to %qT from %qT makes pointer from integer " + "without a cast", type, rhstype); + break; + case ic_init: + pedwarn_init (location, OPT_Wint_conversion, + "initialization of %qT from %qT makes pointer from " + "integer without a cast", type, rhstype); + break; + case ic_return: + pedwarn (location, OPT_Wint_conversion, "returning %qT from a " + "function with return type %qT makes pointer from " + "integer without a cast", rhstype, type); + break; + default: + gcc_unreachable (); + } return convert (type, rhs); } else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - PEDWARN_FOR_ASSIGNMENT (location, expr_loc, - OPT_Wint_conversion, - G_("passing argument %d of %qE makes integer " - "from pointer without a cast"), - G_("assignment makes integer from pointer " - "without a cast"), - G_("initialization makes integer from pointer " - "without a cast"), - G_("return makes integer from pointer " - "without a cast")); + switch (errtype) + { + case ic_argpass: + if (pedwarn (expr_loc, OPT_Wint_conversion, + "passing argument %d of %qE makes integer from " + "pointer without a cast", parmnum, rname)) + inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) + ? DECL_SOURCE_LOCATION (fundecl) : expr_loc, + "expected %qT but argument is of type %qT", + type, rhstype); + break; + case ic_assign: + pedwarn (location, OPT_Wint_conversion, + "assignment to %qT from %qT makes integer from pointer " + "without a cast", type, rhstype); + break; + case ic_init: + pedwarn_init (location, OPT_Wint_conversion, + "initialization of %qT from %qT makes integer from " + "pointer without a cast", type, rhstype); + break; + case ic_return: + pedwarn (location, OPT_Wint_conversion, "returning %qT from a " + "function with return type %qT makes integer from " + "pointer without a cast", rhstype, type); + break; + default: + gcc_unreachable (); + } + return convert (type, rhs); } else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE) @@ -8184,7 +8291,7 @@ pop_init_level (location_t loc, int implicit, ARRAY argument is nonzero for array ranges. Returns false for success. */ static bool -set_designator (location_t loc, int array, +set_designator (location_t loc, bool array, struct obstack *braced_init_obstack) { tree subtype; @@ -8280,7 +8387,7 @@ void set_init_index (location_t loc, tree first, tree last, struct obstack *braced_init_obstack) { - if (set_designator (loc, 1, braced_init_obstack)) + if (set_designator (loc, true, braced_init_obstack)) return; designator_erroneous = 1; @@ -8370,7 +8477,7 @@ set_init_label (location_t loc, tree fieldname, location_t fieldname_loc, { tree field; - if (set_designator (loc, 0, braced_init_obstack)) + if (set_designator (loc, false, braced_init_obstack)) return; designator_erroneous = 1; @@ -8410,7 +8517,7 @@ set_init_label (location_t loc, tree fieldname, location_t fieldname_loc, field = TREE_CHAIN (field); if (field) { - if (set_designator (loc, 0, braced_init_obstack)) + if (set_designator (loc, false, braced_init_obstack)) return; } } @@ -8843,9 +8950,9 @@ find_init_member (tree field, struct obstack * braced_init_obstack) unparenthesized or we should not warn here for it being parenthesized. For other types of VALUE, STRICT_STRING is not used. - PENDING if non-nil means output pending elements that belong - right after this element. (PENDING is normally 1; - it is 0 while outputting pending elements, to avoid recursion.) + PENDING if true means output pending elements that belong + right after this element. (PENDING is normally true; + it is false while outputting pending elements, to avoid recursion.) IMPLICIT is true if value comes from pop_init_level (1), the new initializer has been merged with the existing one @@ -8854,7 +8961,7 @@ find_init_member (tree field, struct obstack * braced_init_obstack) static void output_init_element (location_t loc, tree value, tree origtype, - bool strict_string, tree type, tree field, int pending, + bool strict_string, tree type, tree field, bool pending, bool implicit, struct obstack * braced_init_obstack) { tree semantic_type = NULL_TREE; @@ -9097,7 +9204,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) constructor_unfilled_index)) output_init_element (input_location, elt->value, elt->origtype, true, TREE_TYPE (constructor_type), - constructor_unfilled_index, 0, false, + constructor_unfilled_index, false, false, braced_init_obstack); else if (tree_int_cst_lt (constructor_unfilled_index, elt->purpose)) @@ -9151,7 +9258,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) constructor_unfilled_fields = elt->purpose; output_init_element (input_location, elt->value, elt->origtype, true, TREE_TYPE (elt->purpose), - elt->purpose, 0, false, + elt->purpose, false, false, braced_init_obstack); } else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) @@ -9395,7 +9502,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, push_member_name (constructor_fields); output_init_element (loc, value.value, value.original_type, strict_string, fieldtype, - constructor_fields, 1, implicit, + constructor_fields, true, implicit, braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -9487,7 +9594,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, push_member_name (constructor_fields); output_init_element (loc, value.value, value.original_type, strict_string, fieldtype, - constructor_fields, 1, implicit, + constructor_fields, true, implicit, braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -9539,7 +9646,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, push_array_bounds (tree_to_uhwi (constructor_index)); output_init_element (loc, value.value, value.original_type, strict_string, elttype, - constructor_index, 1, implicit, + constructor_index, true, implicit, braced_init_obstack); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -9574,7 +9681,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, elttype = TYPE_MAIN_VARIANT (constructor_type); output_init_element (loc, value.value, value.original_type, strict_string, elttype, - constructor_index, 1, implicit, + constructor_index, true, implicit, braced_init_obstack); } @@ -9603,7 +9710,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, if (value.value) output_init_element (loc, value.value, value.original_type, strict_string, constructor_type, - NULL_TREE, 1, implicit, + NULL_TREE, true, implicit, braced_init_obstack); constructor_fields = NULL_TREE; } @@ -10735,7 +10842,7 @@ build_vec_cmp (tree_code code, tree type, tree build_binary_op (location_t location, enum tree_code code, - tree orig_op0, tree orig_op1, int convert_p) + tree orig_op0, tree orig_op1, bool convert_p) { tree type0, type1, orig_type0, orig_type1; tree eptype; diff --git a/gcc/calls.c b/gcc/calls.c index 8a23b50fc6666..7599928c7cb0e 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -52,6 +52,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssanames.h" #include "rtl-chkp.h" #include "intl.h" +#include "stringpool.h" +#include "attribs.h" /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */ #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) @@ -1222,32 +1224,38 @@ alloc_max_size (void) else if (!strcasecmp (end, "KiB") || strcmp (end, "KB")) unit = 1024; else if (!strcmp (end, "MB")) - unit = 1000LU * 1000; + unit = HOST_WIDE_INT_UC (1000) * 1000; else if (!strcasecmp (end, "MiB")) - unit = 1024LU * 1024; + unit = HOST_WIDE_INT_UC (1024) * 1024; else if (!strcasecmp (end, "GB")) - unit = 1000LU * 1000 * 1000; + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000; else if (!strcasecmp (end, "GiB")) - unit = 1024LU * 1024 * 1024; + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024; else if (!strcasecmp (end, "TB")) - unit = 1000LU * 1000 * 1000 * 1000; + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000; else if (!strcasecmp (end, "TiB")) - unit = 1024LU * 1024 * 1024 * 1024; + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024; else if (!strcasecmp (end, "PB")) - unit = 1000LU * 1000 * 1000 * 1000 * 1000; + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000; else if (!strcasecmp (end, "PiB")) - unit = 1024LU * 1024 * 1024 * 1024 * 1024; + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024; else if (!strcasecmp (end, "EB")) - unit = 1000LU * 1000 * 1000 * 1000 * 1000 * 1000; + unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000 + * 1000; else if (!strcasecmp (end, "EiB")) - unit = 1024LU * 1024 * 1024 * 1024 * 1024 * 1024; + unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024 + * 1024; else unit = 0; } if (unit) - alloc_object_size_limit - = build_int_cst (ssizetype, limit * unit); + { + wide_int w = wi::uhwi (limit, HOST_BITS_PER_WIDE_INT + 64); + w *= unit; + if (wi::ltu_p (w, alloc_object_size_limit)) + alloc_object_size_limit = wide_int_to_tree (ssizetype, w); + } } } } diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 792ea62cc56e4..394d986c945a3 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -737,23 +737,24 @@ post_order_compute (int *post_order, bool include_entry_exit, basic_block dfs_find_deadend (basic_block bb) { - bitmap visited = BITMAP_ALLOC (NULL); + auto_bitmap visited; + basic_block next = bb; for (;;) { - if (EDGE_COUNT (bb->succs) == 0 - || ! bitmap_set_bit (visited, bb->index)) - { - BITMAP_FREE (visited); - return bb; - } + if (EDGE_COUNT (next->succs) == 0) + return next; + + if (! bitmap_set_bit (visited, next->index)) + return bb; + bb = next; /* If we are in an analyzed cycle make sure to try exiting it. Note this is a heuristic only and expected to work when loop fixup is needed as well. */ if (! bb->loop_father || ! loop_outer (bb->loop_father)) - bb = EDGE_SUCC (bb, 0)->dest; + next = EDGE_SUCC (bb, 0)->dest; else { edge_iterator ei; @@ -761,7 +762,7 @@ dfs_find_deadend (basic_block bb) FOR_EACH_EDGE (e, ei, bb->succs) if (loop_exit_edge_p (bb->loop_father, e)) break; - bb = e ? e->dest : EDGE_SUCC (bb, 0)->dest; + next = e ? e->dest : EDGE_SUCC (bb, 0)->dest; } } diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c9d8118ed4526..573f0c751adfc 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -68,6 +68,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-outof-ssa.h" #include "cfgloop.h" #include "insn-attr.h" /* For INSN_SCHEDULING. */ +#include "stringpool.h" +#include "attribs.h" #include "asan.h" #include "tree-ssa-address.h" #include "output.h" @@ -6527,12 +6529,6 @@ pass_expand::execute (function *fun) TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1; } - /* We are now committed to emitting code for this function. Do any - preparation, such as emitting abstract debug info for the inline - before it gets mangled by optimization. */ - if (cgraph_function_possibly_inlined_p (current_function_decl)) - (*debug_hooks->outlining_inline_function) (current_function_decl); - TREE_ASM_WRITTEN (current_function_decl) = 1; /* After expanding, the return labels are no longer needed. */ diff --git a/gcc/cgraph.c b/gcc/cgraph.c index d7c9ba6179551..69aa6c5bce2f1 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -61,6 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-chkp.h" #include "context.h" #include "gimplify.h" +#include "stringpool.h" +#include "attribs.h" /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */ #include "tree-pass.h" @@ -582,10 +584,11 @@ cgraph_node * cgraph_node::create_same_body_alias (tree alias, tree decl) { cgraph_node *n; -#ifndef ASM_OUTPUT_DEF + /* If aliases aren't supported by the assembler, fail. */ - return NULL; -#endif + if (!TARGET_SUPPORTS_ALIASES) + return NULL; + /* Langhooks can create same body aliases of symbols not defined. Those are useless. Drop them on the floor. */ if (symtab->global_info_ready) diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 6072c567bc366..a287f0dfd4435 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -204,6 +204,8 @@ along with GCC; see the file COPYING3. If not see #include "dbgcnt.h" #include "tree-chkp.h" #include "lto-section-names.h" +#include "stringpool.h" +#include "attribs.h" /* Queue of cgraph nodes scheduled to be added into cgraph. This is a secondary queue used during optimization to accommodate passes that @@ -2462,10 +2464,6 @@ symbol_table::compile (void) fprintf (stderr, "Performing interprocedural optimizations\n"); state = IPA; - /* Offloading requires LTO infrastructure. */ - if (!in_lto_p && g->have_offload) - flag_generate_offload = 1; - /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */ if (flag_generate_lto || flag_generate_offload) lto_streamer_hooks_init (); @@ -2612,6 +2610,10 @@ symbol_table::finalize_compilation_unit (void) /* Gimplify and lower thunks. */ analyze_functions (/*first_time=*/false); + /* Offloading requires LTO infrastructure. */ + if (!in_lto_p && g->have_offload) + flag_generate_offload = 1; + if (!seen_error ()) { /* Emit early debug for reachable functions, and by consequence, diff --git a/gcc/combine.c b/gcc/combine.c index 8dc62b57266ba..b34fb81c97a83 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -6809,9 +6809,7 @@ simplify_set (rtx x) / UNITS_PER_WORD) == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)) - && (WORD_REGISTER_OPERATIONS - || (GET_MODE_SIZE (GET_MODE (src)) - <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) + && (WORD_REGISTER_OPERATIONS || !paradoxical_subreg_p (src)) #ifdef CANNOT_CHANGE_MODE_CLASS && ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER && REG_CANNOT_CHANGE_MODE_P (REGNO (dest), @@ -7456,7 +7454,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos, : BITS_PER_UNIT)) == 0 /* We can't do this if we are widening INNER_MODE (it may not be aligned, for one thing). */ - && GET_MODE_PRECISION (inner_mode) >= GET_MODE_PRECISION (tmode) + && !paradoxical_subreg_p (tmode, inner_mode) && (inner_mode == tmode || (! mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner)) @@ -7490,26 +7488,15 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos, return a new hard register. */ if (pos || in_dest) { - HOST_WIDE_INT final_word = pos / BITS_PER_WORD; - - if (WORDS_BIG_ENDIAN - && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD) - final_word = ((GET_MODE_SIZE (inner_mode) - - GET_MODE_SIZE (tmode)) - / UNITS_PER_WORD) - final_word; - - final_word *= UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN && - GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (tmode)) - final_word += (GET_MODE_SIZE (inner_mode) - - GET_MODE_SIZE (tmode)) % UNITS_PER_WORD; + unsigned int offset + = subreg_offset_from_lsb (tmode, inner_mode, pos); /* Avoid creating invalid subregs, for example when simplifying (x>>32)&255. */ - if (!validate_subreg (tmode, inner_mode, inner, final_word)) + if (!validate_subreg (tmode, inner_mode, inner, offset)) return NULL_RTX; - new_rtx = gen_rtx_SUBREG (tmode, inner, final_word); + new_rtx = gen_rtx_SUBREG (tmode, inner, offset); } else new_rtx = gen_lowpart (tmode, inner); @@ -7669,7 +7656,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos, /* If bytes are big endian and we had a paradoxical SUBREG, we must adjust OFFSET to compensate. */ if (BYTES_BIG_ENDIAN - && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode)) + && paradoxical_subreg_p (is_mode, inner_mode)) offset -= GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (inner_mode); /* We can now move to the desired byte. */ @@ -8529,7 +8516,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask, /* If X is narrower than MODE and we want all the bits in X's mode, just get X in the proper mode. */ - if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode) + if (paradoxical_subreg_p (mode, GET_MODE (x)) && (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0) return gen_lowpart (mode, x); @@ -9408,7 +9395,7 @@ rtx_equal_for_field_assignment_p (rtx x, rtx y, bool widen_x) { if (widen_x && GET_MODE (x) != GET_MODE (y)) { - if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (y))) + if (paradoxical_subreg_p (GET_MODE (x), GET_MODE (y))) return 0; if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) return 0; @@ -11488,7 +11475,7 @@ gen_lowpart_for_combine (machine_mode omode, rtx x) /* If we want to refer to something bigger than the original memref, generate a paradoxical subreg instead. That will force a reload of the original memref X. */ - if (isize < osize) + if (paradoxical_subreg_p (omode, imode)) return gen_rtx_SUBREG (omode, x, 0); if (WORDS_BIG_ENDIAN) @@ -12145,8 +12132,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) /* If the inner mode is narrower and we are extracting the low part, we can treat the SUBREG as if it were a ZERO_EXTEND. */ - if (subreg_lowpart_p (op0) - && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0))) < mode_width) + if (paradoxical_subreg_p (op0)) ; else if (subreg_lowpart_p (op0) && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT diff --git a/gcc/common.opt b/gcc/common.opt index 78cfa568a95d1..1331008f81107 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1303,8 +1303,8 @@ Common Report Var(flag_early_inlining) Init(1) Optimization Perform early inlining. feliminate-dwarf2-dups -Common Report Var(flag_eliminate_dwarf2_dups) -Perform DWARF duplicate elimination. +Common Ignore +Does nothing. Preserved for backward compatibility. fipa-sra Common Report Var(flag_ipa_sra) Init(0) Optimization @@ -2691,8 +2691,9 @@ fvar-tracking-uninit Common Report Var(flag_var_tracking_uninit) PerFunction Perform variable tracking and also tag variables that are uninitialized. +; Alias to enable both -ftree-loop-vectorize and -ftree-slp-vectorize. ftree-vectorize -Common Report Var(flag_tree_vectorize) Optimization +Common Report Optimization Enable vectorization on trees. ftree-vectorizer-verbose= @@ -2700,11 +2701,11 @@ Common Joined RejectNegative Ignore Does nothing. Preserved for backward compatibility. ftree-loop-vectorize -Common Report Var(flag_tree_loop_vectorize) Optimization +Common Report Var(flag_tree_loop_vectorize) Optimization EnabledBy(ftree-vectorize) Enable loop vectorization on trees. ftree-slp-vectorize -Common Report Var(flag_tree_slp_vectorize) Optimization +Common Report Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize) Enable basic block vectorization (SLP) on trees. fvect-cost-model= diff --git a/gcc/config.gcc b/gcc/config.gcc index fdf4cb845ae1d..cc56c57686464 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -457,6 +457,7 @@ powerpc*-*-*) extra_objs="rs6000-string.o rs6000-p8swap.o" extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h" extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h" + extra_headers="${extra_headers} xmmintrin.h mm_malloc.h" extra_headers="${extra_headers} mmintrin.h x86intrin.h" extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h" extra_headers="${extra_headers} paired.h" @@ -653,7 +654,7 @@ case ${target} in cxx_target_objs="${cxx_target_objs} darwin-c.o" fortran_target_objs="darwin-f.o" target_has_targetcm=yes - extra_objs="darwin.o" + extra_objs="${extra_objs} darwin.o" extra_gcc_objs="darwin-driver.o" default_use_cxa_atexit=yes use_gcc_stdint=wrap @@ -1059,11 +1060,23 @@ arc*-*-linux*) big*) tm_file="arc/big.h ${tm_file}" esac ;; -arm-wrs-vxworks) - tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h" +arm-wrs-vxworks|arm-wrs-vxworks7) extra_options="${extra_options} arm/vxworks.opt" tmake_file="${tmake_file} arm/t-arm arm/t-vxworks" - target_cpu_cname="arm6" + case $target in + *-vxworks7) + # VxWorks7 on ARM adheres to the ARM Base Platform ABI + tmake_file="${tmake_file} arm/t-bpabi" + tm_file="arm/bpabi.h ${tm_file}" + # The BPABI long long divmod functions return a 128-bit value in + # registers r0-r3. + need_64bit_hwint=yes + default_use_cxa_atexit=yes + ;; + *) ;; + esac + tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h" + target_cpu_cname="arm8" ;; arm*-*-freebsd*) # ARM FreeBSD EABI tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h" @@ -2430,7 +2443,7 @@ powerpc-*-rtems*spe*) ;; powerpc-*-rtems*) tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h" - extra_options="${extra_options} rs6000/sysv4.opt" + extra_options="${extra_options} rs6000/sysv4.opt rs6000/linux64.opt" tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm" ;; powerpc*-*-linux*spe*) diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index b8d0ba6b69e3e..10893324d3fd8 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -65,8 +65,8 @@ AARCH64_CORE("thunderxt83", thunderxt83, thunderx, 8A, AARCH64_FL_FOR_ARCH AARCH64_CORE("xgene1", xgene1, xgene1, 8A, AARCH64_FL_FOR_ARCH8, xgene1, 0x50, 0x000, -1) /* Qualcomm ('Q') cores. */ -AARCH64_CORE("falkor", falkor, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1) -AARCH64_CORE("qdf24xx", qdf24xx, cortexa57, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1) +AARCH64_CORE("falkor", falkor, falkor, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1) +AARCH64_CORE("qdf24xx", qdf24xx, falkor, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, qdf24xx, 0x51, 0xC00, -1) /* Samsung ('S') cores. */ AARCH64_CORE("exynos-m1", exynosm1, exynosm1, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC | AARCH64_FL_CRYPTO, exynosm1, 0x53, 0x001, -1) diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def index c4f059ab7c555..a989a2ec23e53 100644 --- a/gcc/config/aarch64/aarch64-option-extensions.def +++ b/gcc/config/aarch64/aarch64-option-extensions.def @@ -65,6 +65,6 @@ AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, "lrcpc") /* Enabling "rdma" also enables "fp", "simd". Disabling "rdma" just disables "rdma". */ -AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "rdma") +AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "asimdrdm") #undef AARCH64_OPT_EXTENSION diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 011fcec07958f..f3e084f8778d7 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -23,7 +23,10 @@ (match_operand:VALL_F16 1 "general_operand" ""))] "TARGET_SIMD" " - if (GET_CODE (operands[0]) == MEM) + if (GET_CODE (operands[0]) == MEM + && !(aarch64_simd_imm_zero (operands[1], mode) + && aarch64_legitimate_address_p (mode, operands[0], + PARALLEL, 1))) operands[1] = force_reg (mode, operands[1]); " ) @@ -94,63 +97,66 @@ (define_insn "*aarch64_simd_mov" [(set (match_operand:VD 0 "nonimmediate_operand" - "=w, m, w, ?r, ?w, ?r, w") + "=w, m, m, w, ?r, ?w, ?r, w") (match_operand:VD 1 "general_operand" - "m, w, w, w, r, r, Dn"))] + "m, Dz, w, w, w, r, r, Dn"))] "TARGET_SIMD && (register_operand (operands[0], mode) - || register_operand (operands[1], mode))" + || aarch64_simd_reg_or_zero (operands[1], mode))" { switch (which_alternative) { - case 0: return "ldr\\t%d0, %1"; - case 1: return "str\\t%d1, %0"; - case 2: return "mov\t%0., %1."; - case 3: return "umov\t%0, %1.d[0]"; - case 4: return "fmov\t%d0, %1"; - case 5: return "mov\t%0, %1"; - case 6: + case 0: return "ldr\t%d0, %1"; + case 1: return "str\txzr, %0"; + case 2: return "str\t%d1, %0"; + case 3: return "mov\t%0., %1."; + case 4: return "umov\t%0, %1.d[0]"; + case 5: return "fmov\t%d0, %1"; + case 6: return "mov\t%0, %1"; + case 7: return aarch64_output_simd_mov_immediate (operands[1], mode, 64); default: gcc_unreachable (); } } - [(set_attr "type" "neon_load1_1reg, neon_store1_1reg,\ + [(set_attr "type" "neon_load1_1reg, neon_stp, neon_store1_1reg,\ neon_logic, neon_to_gp, f_mcr,\ mov_reg, neon_move")] ) (define_insn "*aarch64_simd_mov" [(set (match_operand:VQ 0 "nonimmediate_operand" - "=w, m, w, ?r, ?w, ?r, w") + "=w, Ump, m, w, ?r, ?w, ?r, w") (match_operand:VQ 1 "general_operand" - "m, w, w, w, r, r, Dn"))] + "m, Dz, w, w, w, r, r, Dn"))] "TARGET_SIMD && (register_operand (operands[0], mode) - || register_operand (operands[1], mode))" + || aarch64_simd_reg_or_zero (operands[1], mode))" { switch (which_alternative) { case 0: - return "ldr\\t%q0, %1"; + return "ldr\t%q0, %1"; case 1: - return "str\\t%q1, %0"; + return "stp\txzr, xzr, %0"; case 2: - return "mov\t%0., %1."; + return "str\t%q1, %0"; case 3: + return "mov\t%0., %1."; case 4: case 5: - return "#"; case 6: + return "#"; + case 7: return aarch64_output_simd_mov_immediate (operands[1], mode, 128); default: gcc_unreachable (); } } [(set_attr "type" "neon_load1_1reg, neon_store1_1reg,\ - neon_logic, multiple, multiple, multiple,\ - neon_move") - (set_attr "length" "4,4,4,8,8,8,4")] + neon_stp, neon_logic, multiple, multiple,\ + multiple, neon_move") + (set_attr "length" "4,4,4,4,8,8,8,4")] ) ;; When storing lane zero we can use the normal STR and its more permissive @@ -351,6 +357,35 @@ } ) +(define_expand "xorsign3" + [(match_operand:VHSDF 0 "register_operand") + (match_operand:VHSDF 1 "register_operand") + (match_operand:VHSDF 2 "register_operand")] + "TARGET_SIMD" +{ + + machine_mode imode = mode; + rtx v_bitmask = gen_reg_rtx (imode); + rtx op1x = gen_reg_rtx (imode); + rtx op2x = gen_reg_rtx (imode); + + rtx arg1 = lowpart_subreg (imode, operands[1], mode); + rtx arg2 = lowpart_subreg (imode, operands[2], mode); + + int bits = GET_MODE_UNIT_BITSIZE (mode) - 1; + + emit_move_insn (v_bitmask, + aarch64_simd_gen_const_vector_dup (mode, + HOST_WIDE_INT_M1U << bits)); + + emit_insn (gen_and3 (op2x, v_bitmask, arg2)); + emit_insn (gen_xor3 (op1x, arg1, op2x)); + emit_move_insn (operands[0], + lowpart_subreg (mode, op1x, imode)); + DONE; +} +) + (define_expand "copysign3" [(match_operand:VHSDF 0 "register_operand") (match_operand:VHSDF 1 "register_operand") @@ -5617,9 +5652,9 @@ DONE; }) -;; Standard pattern name vec_init. +;; Standard pattern name vec_init. -(define_expand "vec_init" +(define_expand "vec_init" [(match_operand:VALL_F16 0 "register_operand" "") (match_operand 1 "" "")] "TARGET_SIMD" @@ -5674,9 +5709,9 @@ "urecpe\\t%0., %1." [(set_attr "type" "neon_fp_recpe_")]) -;; Standard pattern name vec_extract. +;; Standard pattern name vec_extract. -(define_expand "vec_extract" +(define_expand "vec_extract" [(match_operand: 0 "aarch64_simd_nonimmediate_operand" "") (match_operand:VALL_F16 1 "register_operand" "") (match_operand:SI 2 "immediate_operand" "")] diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 055ebafb83054..28c4e0e647660 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -33,6 +33,7 @@ #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -3069,7 +3070,7 @@ aarch64_pushwb_single_reg (machine_mode mode, unsigned regno, reg = gen_rtx_REG (mode, regno); mem = gen_rtx_PRE_MODIFY (Pmode, base_rtx, plus_constant (Pmode, base_rtx, -adjustment)); - mem = gen_rtx_MEM (mode, mem); + mem = gen_frame_mem (mode, mem); insn = emit_move_insn (mem, reg); RTX_FRAME_RELATED_P (insn) = 1; @@ -3157,7 +3158,7 @@ aarch64_pop_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment, { rtx mem = plus_constant (Pmode, stack_pointer_rtx, adjustment); mem = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx, mem); - emit_move_insn (reg1, gen_rtx_MEM (mode, mem)); + emit_move_insn (reg1, gen_frame_mem (mode, mem)); } else { @@ -3233,8 +3234,6 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset, unsigned start, unsigned limit, bool skip_wb) { rtx_insn *insn; - rtx (*gen_mem_ref) (machine_mode, rtx) = (frame_pointer_needed - ? gen_frame_mem : gen_rtx_MEM); unsigned regno; unsigned regno2; @@ -3255,8 +3254,8 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset, reg = gen_rtx_REG (mode, regno); offset = start_offset + cfun->machine->frame.reg_offset[regno]; - mem = gen_mem_ref (mode, plus_constant (Pmode, stack_pointer_rtx, - offset)); + mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, + offset)); regno2 = aarch64_next_callee_save (regno + 1, limit); @@ -3270,8 +3269,8 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset, rtx mem2; offset = start_offset + cfun->machine->frame.reg_offset[regno2]; - mem2 = gen_mem_ref (mode, plus_constant (Pmode, stack_pointer_rtx, - offset)); + mem2 = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, + offset)); insn = emit_insn (aarch64_gen_store_pair (mode, mem, reg, mem2, reg2)); @@ -3300,8 +3299,6 @@ aarch64_restore_callee_saves (machine_mode mode, unsigned limit, bool skip_wb, rtx *cfi_ops) { rtx base_rtx = stack_pointer_rtx; - rtx (*gen_mem_ref) (machine_mode, rtx) = (frame_pointer_needed - ? gen_frame_mem : gen_rtx_MEM); unsigned regno; unsigned regno2; HOST_WIDE_INT offset; @@ -3322,7 +3319,7 @@ aarch64_restore_callee_saves (machine_mode mode, reg = gen_rtx_REG (mode, regno); offset = start_offset + cfun->machine->frame.reg_offset[regno]; - mem = gen_mem_ref (mode, plus_constant (Pmode, base_rtx, offset)); + mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); regno2 = aarch64_next_callee_save (regno + 1, limit); @@ -3335,7 +3332,7 @@ aarch64_restore_callee_saves (machine_mode mode, rtx mem2; offset = start_offset + cfun->machine->frame.reg_offset[regno2]; - mem2 = gen_mem_ref (mode, plus_constant (Pmode, base_rtx, offset)); + mem2 = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); emit_insn (aarch64_gen_load_pair (mode, reg, mem, reg2, mem2)); *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops); @@ -4733,9 +4730,14 @@ aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval) CONST_DOUBLE_REAL_VALUE (value), REAL_MODE_FORMAT (mode)); - ival = zext_hwi (res[0], 32); - if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (DFmode)) - ival |= (zext_hwi (res[1], 32) << 32); + if (mode == DFmode) + { + int order = BYTES_BIG_ENDIAN ? 1 : 0; + ival = zext_hwi (res[order], 32); + ival |= (zext_hwi (res[1 - order], 32) << 32); + } + else + ival = zext_hwi (res[0], 32); *intval = ival; return true; @@ -4787,10 +4789,6 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode) if (!TARGET_SIMD) return false; - /* We make a general exception for 0. */ - if (aarch64_float_const_zero_rtx_p (x)) - return true; - machine_mode vmode, imode; unsigned HOST_WIDE_INT ival; @@ -4800,6 +4798,10 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode) if (!aarch64_reinterpret_float_as_int (x, &ival)) return false; + /* We make a general exception for 0. */ + if (aarch64_float_const_zero_rtx_p (x)) + return true; + imode = int_mode_for_mode (mode); } else if (GET_CODE (x) == CONST_INT diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index fc799479c819a..c1bca07308d84 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -231,6 +231,7 @@ (include "../arm/cortex-a53.md") (include "../arm/cortex-a57.md") (include "../arm/exynos-m1.md") +(include "falkor.md") (include "thunderx.md") (include "../arm/xgene1.md") (include "thunderx2t99.md") @@ -494,7 +495,7 @@ const0_rtx), operands[0], operands[2], operands[4])); - operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (VOIDmode, operands[3])); + operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3])); emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0], operands[3])); DONE; @@ -1076,7 +1077,7 @@ [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r") (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))] "TARGET_FLOAT && (register_operand (operands[0], HFmode) - || aarch64_reg_or_fp_float (operands[1], HFmode))" + || aarch64_reg_or_fp_zero (operands[1], HFmode))" "@ movi\\t%0.4h, #0 fmov\\t%h0, %w1 @@ -1099,7 +1100,7 @@ [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r") (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))] "TARGET_FLOAT && (register_operand (operands[0], SFmode) - || aarch64_reg_or_fp_float (operands[1], SFmode))" + || aarch64_reg_or_fp_zero (operands[1], SFmode))" "@ movi\\t%0.2s, #0 fmov\\t%s0, %w1 @@ -1123,7 +1124,7 @@ [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r") (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))] "TARGET_FLOAT && (register_operand (operands[0], DFmode) - || aarch64_reg_or_fp_float (operands[1], DFmode))" + || aarch64_reg_or_fp_zero (operands[1], DFmode))" "@ movi\\t%d0, #0 fmov\\t%d0, %x1 @@ -5178,6 +5179,42 @@ } ) +;; For xorsign (x, y), we want to generate: +;; +;; LDR d2, #1<<63 +;; AND v3.8B, v1.8B, v2.8B +;; EOR v0.8B, v0.8B, v3.8B +;; + +(define_expand "xorsign3" + [(match_operand:GPF 0 "register_operand") + (match_operand:GPF 1 "register_operand") + (match_operand:GPF 2 "register_operand")] + "TARGET_FLOAT && TARGET_SIMD" +{ + + machine_mode imode = mode; + rtx mask = gen_reg_rtx (imode); + rtx op1x = gen_reg_rtx (imode); + rtx op2x = gen_reg_rtx (imode); + + int bits = GET_MODE_BITSIZE (mode) - 1; + emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits, + imode))); + + emit_insn (gen_and3 (op2x, mask, + lowpart_subreg (imode, operands[2], + mode))); + emit_insn (gen_xor3 (op1x, + lowpart_subreg (imode, operands[1], + mode), + op2x)); + emit_move_insn (operands[0], + lowpart_subreg (mode, op1x, imode)); + DONE; +} +) + ;; ------------------------------------------------------------------- ;; Reload support ;; ------------------------------------------------------------------- diff --git a/gcc/config/aarch64/falkor.md b/gcc/config/aarch64/falkor.md new file mode 100644 index 0000000000000..b422ab30c4440 --- /dev/null +++ b/gcc/config/aarch64/falkor.md @@ -0,0 +1,681 @@ +;; Falkor pipeline description +;; Copyright (C) 2017 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_automaton "falkor") + +;; Complex int instructions (e.g. multiply and divide) execute in the X +;; pipeline. Simple int instructions execute in the X, Y, and Z pipelines. + +(define_cpu_unit "falkor_x" "falkor") +(define_cpu_unit "falkor_y" "falkor") +(define_cpu_unit "falkor_z" "falkor") + +;; Branches execute in the B pipeline or in one of the int pipelines depending +;; on how complex it is. Simple int insns (like movz) can also execute here. + +(define_cpu_unit "falkor_b" "falkor") + +;; Vector and FP insns execute in the VX and VY pipelines. + +(define_automaton "falkor_vfp") + +(define_cpu_unit "falkor_vx" "falkor_vfp") +(define_cpu_unit "falkor_vy" "falkor_vfp") + +;; Loads execute in the LD pipeline. +;; Stores execute in the ST, SD, and VSD pipelines, for address, data, and +;; vector data. + +(define_automaton "falkor_mem") + +(define_cpu_unit "falkor_ld" "falkor_mem") +(define_cpu_unit "falkor_st" "falkor_mem") +(define_cpu_unit "falkor_sd" "falkor_mem") +(define_cpu_unit "falkor_vsd" "falkor_mem") + +;; The GTOV and VTOG pipelines are for general to vector reg moves, and vice +;; versa. + +(define_cpu_unit "falkor_gtov" "falkor") +(define_cpu_unit "falkor_vtog" "falkor") + +;; Common reservation combinations. + +(define_reservation "falkor_vxvy" "falkor_vx|falkor_vy") +(define_reservation "falkor_zb" "falkor_z|falkor_b") +(define_reservation "falkor_xyz" "falkor_x|falkor_y|falkor_z") +(define_reservation "falkor_xyzb" "falkor_x|falkor_y|falkor_z|falkor_b") + +;; SIMD Floating-Point Instructions + +(define_insn_reservation "falkor_afp_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_neg_s,neon_fp_neg_d,neon_fp_abs_s,neon_fp_abs_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_1_vxvy_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_neg_s_q,neon_fp_neg_d_q,neon_fp_abs_s_q,neon_fp_abs_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_2_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_minmax_s,neon_fp_minmax_d,neon_fp_reduc_minmax_s,neon_fp_reduc_minmax_d,neon_fp_compare_s,neon_fp_compare_d,neon_fp_round_s,neon_fp_round_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_2_vxvy_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_minmax_s_q,neon_fp_minmax_d_q,neon_fp_compare_s_q,neon_fp_compare_d_q,neon_fp_round_s_q,neon_fp_round_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_3_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_reduc_minmax_s_q,neon_fp_reduc_minmax_d_q,neon_fp_abd_s,neon_fp_abd_d,neon_fp_addsub_s,neon_fp_addsub_d,neon_fp_reduc_add_s,neon_fp_reduc_add_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_3_vxvy_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_abd_s_q,neon_fp_abd_d_q,neon_fp_addsub_s_q,neon_fp_addsub_d_q,neon_fp_reduc_add_s_q,neon_fp_reduc_add_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_4_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_to_int_s,neon_fp_to_int_d,neon_int_to_fp_s,neon_int_to_fp_d,neon_fp_cvt_widen_h,neon_fp_cvt_widen_s")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_4_vxvy_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_to_int_s_q,neon_fp_to_int_d_q,neon_int_to_fp_s_q,neon_int_to_fp_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_5_vxvy_mul" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mul_s,neon_fp_mul_s_scalar")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_5_vxvy_mla" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mla_s,neon_fp_mla_s_scalar")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_5_vxvy_vxvy_mul" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mul_s_q,neon_fp_mul_s_scalar_q")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_5_vxvy_vxvy_mla" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mla_s_q,neon_fp_mla_s_scalar_q")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_6_vxvy_mul" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mul_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_6_vxvy_mla" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mla_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_afp_6_vxvy_vxvy_mul" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mul_d_q,neon_fp_mul_d_scalar_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_6_vxvy_vxvy_mla" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_mla_d_q,neon_fp_mla_d_scalar_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_afp_4_vxvy_vxvy_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_cvt_narrow_s_q,neon_fp_cvt_narrow_d_q")) + "falkor_vxvy+falkor_vxvy,falkor_vxvy") + +(define_insn_reservation "falkor_afp_6_vx_vy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_div_s")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_afp_11_vx_vy" 11 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_div_d")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_afp_6_vx_vy_vx_vy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_div_s_q")) + "(falkor_vx+falkor_vy),(falkor_vx+falkor_vy)") + +(define_insn_reservation "falkor_afp_11_vx_vy_vx_vy" 11 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_div_d_q")) + "(falkor_vx+falkor_vy),(falkor_vx+falkor_vy)") + +(define_insn_reservation "falkor_afp_12_vx_vy" 12 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_sqrt_s")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_afp_22_vx_vy" 22 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_sqrt_d")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_afp_12_vx_vy_vx_vy" 12 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_sqrt_s_q")) + "(falkor_vx+falkor_vy),(falkor_vx+falkor_vy)") + +(define_insn_reservation "falkor_afp_22_vx_vy_vx_vy" 22 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_sqrt_d_q")) + "(falkor_vx+falkor_vy),(falkor_vx+falkor_vy)") + +;; SIMD Integer Instructions + +(define_insn_reservation "falkor_ai_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_add,neon_reduc_add,neon_logic,neon_neg,neon_sub")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_1_vxvy_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_shift_imm_long,neon_add_q,neon_reduc_add_q,neon_logic_q,neon_neg_q,neon_sub_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_ai_2_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_add_long,neon_sub_long,neon_add_halve,neon_sub_halve,neon_shift_imm,neon_shift_reg,neon_minmax,neon_abs,neon_compare,neon_compare_zero,neon_tst")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_2_vxvy_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_add_halve_q,neon_sub_halve_q,neon_shift_imm_q,neon_shift_reg_q,neon_minmax_q,neon_abs_q,neon_compare_q,neon_compare_zero_q,neon_tst_q,neon_reduc_add_long")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_ai_3_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_shift_acc,neon_reduc_add_acc,neon_abd,neon_qadd,neon_qsub,neon_qabs,neon_qneg,neon_sat_shift_imm,neon_sat_shift_imm_narrow_q,neon_sat_shift_reg,neon_reduc_minmax")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_reduc_minmax_q")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_3_vxvy_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_shift_acc_q,neon_reduc_add_acc_q,neon_abd_q,neon_abd_long,neon_qadd_q,neon_qsub_q,neon_qabs_q,neon_qneg_q,neon_sat_shift_imm_q,neon_sat_shift_reg_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy_mul" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_mul_b,neon_mul_h,neon_mul_s,neon_mul_h_scalar,neon_mul_s_scalar,neon_sat_mul_b,neon_sat_mul_h,neon_sat_mul_s,neon_sat_mul_h_scalar,neon_sat_mul_s_scalar")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy_mla" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_mla_b,neon_mla_h,neon_mla_s,neon_mla_h_scalar,neon_mla_s_scalar")) + "falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy_vxvy_mul" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_mul_b_q,neon_mul_h_q,neon_mul_s_q,neon_mul_h_scalar_q,neon_mul_s_scalar_q,neon_sat_mul_b_q,neon_sat_mul_h_q,neon_sat_mul_s_q,neon_mul_b_long,neon_mul_h_long,neon_mul_s_long,neon_mul_d_long,neon_mul_h_scalar_long,neon_mul_s_scalar_long,neon_sat_mul_b_long,neon_sat_mul_h_long,neon_sat_mul_s_long,neon_sat_mul_h_scalar_q,neon_sat_mul_s_scalar_q,neon_sat_mul_h_scalar_long,neon_sat_mul_s_scalar_long")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy_vxvy_mla" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_mla_b_q,neon_mla_h_q,neon_mla_s_q,neon_mla_h_scalar_q,neon_mla_s_scalar_q,neon_mla_b_long,neon_mla_h_long,neon_mla_s_long,neon_mla_h_scalar_long,neon_mla_s_scalar_long,neon_sat_mla_b_long,neon_sat_mla_h_long,neon_sat_mla_s_long,neon_sat_mla_h_scalar_long,neon_sat_mla_s_scalar_long")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_ai_4_vxvy_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_add_halve_narrow_q,neon_sub_halve_narrow_q,neon_arith_acc")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_2_ai_vxvy_vxvy_vxvy_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_add_widen,neon_sub_widen")) + "(falkor_vxvy+falkor_vxvy),(falkor_vxvy+falkor_vxvy)") + +(define_insn_reservation "falkor_4_ai_vxvy_vxvy_vxvy_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_arith_acc_q")) + "(falkor_vxvy+falkor_vxvy),(falkor_vxvy+falkor_vxvy)") + +;; SIMD Load Instructions + +(define_insn_reservation "falkor_ald_4_ld" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_1reg,neon_load1_1reg_q,neon_load1_all_lanes,neon_load2_one_lane")) + "falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_none" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_2reg,neon_load2_2reg,neon_load2_all_lanes")) + "falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_ld" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_2reg_q,neon_load2_2reg_q,neon_load2_all_lanes_q,neon_load3_one_lane,neon_load4_one_lane,neon_ldp,neon_ldp_q")) + "falkor_ld,falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_ld_none" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_3reg,neon_load3_3reg,neon_load3_all_lanes")) + "falkor_ld,falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_ld_ld" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_3reg_q,neon_load3_3reg_q,neon_load3_all_lanes_q")) + "falkor_ld,falkor_ld,falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_ld_none_none" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_4reg,neon_load4_4reg")) + "falkor_ld,falkor_ld") + +(define_insn_reservation "falkor_ald_4_ld_ld_ld_ld" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_load1_4reg_q,neon_load4_4reg_q,neon_load4_all_lanes,neon_load4_all_lanes_q")) + "falkor_ld,falkor_ld,falkor_ld,falkor_ld") + +;; Arithmetic and Logical Instructions + +(define_insn_reservation "falkor_alu_1_xyz" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "alus_sreg,alus_imm,alus_shift_imm,csel,adc_reg,alu_imm,alu_sreg,alu_shift_imm,alu_ext,alus_ext,logic_imm,logic_reg,logic_shift_imm,logics_imm,logics_reg,logics_shift_imm,mov_reg")) + "falkor_xyz") + +;; SIMD Miscellaneous Instructions + +;; No separate type for ins and dup. But this is correct for both. + +(define_insn_reservation "falkor_am_3_gtov" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_from_gp")) + "falkor_gtov") + +;; No separate type for ins and dup. Assuming dup is more common. Ins is +;; gtov+vxvy and latency of 4. + +(define_insn_reservation "falkor_am_3_gtov_gtov" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_from_gp_q")) + "falkor_gtov,falkor_gtov") + +;; neon_to_gp_q is used for 32-bit ARM instructions that move 64-bits of data +;; so no use needed here. + +(define_insn_reservation "falkor_am_3_vtog" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_to_gp")) + "falkor_vtog") + +(define_insn_reservation "falkor_am_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_bsl,neon_dup,neon_ext,neon_ins,neon_ins_q,neon_move,neon_rev,neon_tbl1,neon_permute,neon_shift_imm_narrow_q")) + "falkor_vxvy") + +(define_insn_reservation "falkor_am_1_vxvy_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_bsl_q,neon_dup_q,neon_ext_q,neon_move_q,neon_rev_q,neon_tbl1_q,neon_permute_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_am_2_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_cls,neon_cnt,neon_rbit")) + "falkor_vxvy") + +(define_insn_reservation "falkor_am_4_vxvy_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_cls_q,neon_cnt_q,neon_rbit_q,neon_tbl2")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_am_3_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recpe_s,neon_fp_recpe_d,neon_fp_rsqrte_s,neon_fp_rsqrte_d,neon_fp_recpx_s,neon_fp_recpx_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_am_3_vxvy_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recpe_s_q,neon_fp_recpe_d_q,neon_fp_rsqrte_s_q,neon_fp_rsqrte_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_am_5_vxvy" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recps_s")) + "falkor_vxvy") + +(define_insn_reservation "falkor_am_5_vxvy_vxvy" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recps_s_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_am_6_vxvy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recps_d,neon_fp_rsqrts_d")) + "falkor_vxvy") + +(define_insn_reservation "falkor_am_6_vxvy_vxvy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_fp_recps_d_q,neon_fp_rsqrts_d_q")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_am_5_vxvy_vxvy_vxvy" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_tbl2_q,neon_tbl3")) + "(falkor_vxvy+falkor_vxvy),falkor_vxvy") + +(define_insn_reservation "falkor_am_6_vxvy_vxvy_vxvy_vxvy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_tbl3_q,neon_tbl4")) + "(falkor_vxvy+falkor_vxvy),(falkor_vxvy+falkor_vxvy)") + +(define_insn_reservation "falkor_am_7_vxvy_vxvy_vxvy_vxvy_vxvy" 7 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_tbl4_q")) + "(falkor_vxvy+falkor_vxvy),(falkor_vxvy+falkor_vxvy),falkor_vxvy") + +;; SIMD Store Instructions + +;; ??? stp is neon_store1_2reg in aarch64.md, but neon_stp in aarch64-simd.md. +;; Similarly with ldp. + +(define_insn_reservation "falkor_ast_st_vsd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_store1_1reg,neon_store1_1reg_q,neon_store1_one_lane,neon_store1_one_lane_q,neon_store1_2reg,neon_store2_2reg,neon_store2_one_lane,neon_store2_one_lane_q,neon_stp")) + "falkor_st+falkor_vsd") + +(define_insn_reservation "falkor_as_0_st_vsd_st_vsd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_store1_2reg_q,neon_store1_3reg,neon_store1_4reg,neon_store2_2reg_q,neon_store3_3reg,neon_store4_4reg,neon_store3_one_lane,neon_store3_one_lane_q,neon_store4_one_lane,neon_store4_one_lane_q,neon_stp_q")) + "(falkor_st+falkor_vsd),(falkor_st+falkor_vsd)") + +(define_insn_reservation "falkor_as_0_st_vsd_st_vsd_st_vsd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_store1_3reg_q,neon_store3_3reg_q")) + "(falkor_st+falkor_vsd),(falkor_st+falkor_vsd),(falkor_st+falkor_vsd)") + +(define_insn_reservation "falkor_as_0_st_vsd_st_vsd_st_vsd_st_vsd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "neon_store1_4reg_q,neon_store4_4reg_q")) + "(falkor_st+falkor_vsd),(falkor_st+falkor_vsd),(falkor_st+falkor_vsd),(falkor_st+falkor_vsd)") + +;; Branch Instructions + +(define_insn_reservation "falkor_branch_0_zb" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "branch")) + "falkor_zb") + +(define_insn_reservation "falkor_call_0_xyzb" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "call")) + "falkor_xyzb") + +;; Cryptography Extensions + +(define_insn_reservation "falkor_cry_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_sha1_fast")) + "falkor_vxvy") + +(define_insn_reservation "falkor_cry_2_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_aesmc")) + "falkor_vxvy") + +(define_insn_reservation "falkor_cry_2_vxvy_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_sha1_xor,crypto_sha256_fast,crypto_pmull")) + "falkor_vxvy+falkor_vxvy") + +(define_insn_reservation "falkor_cry_4_vy_vx" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_sha1_slow")) + "falkor_vy+falkor_vx") + +(define_insn_reservation "falkor_cry_6_vy_vx" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_sha256_slow")) + "falkor_vy+falkor_vx") + +(define_insn_reservation "falkor_cry_3_vxvy_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crypto_aese")) + "falkor_vxvy+falkor_vxvy") + +;; FP Load Instructions + +(define_insn_reservation "falkor_fld_4_ld" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_loads,f_loadd")) + "falkor_ld") + +;; No separate FP store section, these are found in the SIMD store section. + +(define_insn_reservation "falkor_fld_0_st_vsd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_stores,f_stored")) + "falkor_st+falkor_vsd") + +;; FP Data Processing Instructions + +(define_insn_reservation "falkor_fpdt_0_vxvy" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fcmps,fcmpd,fccmps,fccmpd")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_5_vtog" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_cvtf2i")) + "falkor_vtog") + +(define_insn_reservation "falkor_fpdt_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "ffariths,ffarithd,fcsel")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_2_vxvy" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_minmaxd,f_minmaxs,f_rintd,f_rints")) + "falkor_vxvy") + +;; Scalar FP ABD is handled same as vector FP ABD. + +(define_insn_reservation "falkor_fpdt_3_vxvy" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "faddd,fadds")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_4_vxvy" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_cvt")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_5_vxvy_mul" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fmuls")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_5_vxvy_mla" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fmacs,ffmas")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_6_vxvy_mul" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fmuld")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_6_vxvy_mla" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fmacd,ffmad")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_6_vx_vy" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fdivs")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_fpdt_11_vx_vy" 11 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fdivd")) + "falkor_vx+falkor_vy") + +(define_insn_reservation "falkor_fpdt_12_vx_vy" 12 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fsqrts")) + "falkor_vxvy") + +(define_insn_reservation "falkor_fpdt_22_vx_vy" 22 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fsqrtd")) + "falkor_vxvy") + +;; FP Miscellaneous Instructions + +(define_insn_reservation "falkor_fpmsc_3_vtog" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_mrc")) + "falkor_vtog") + +(define_insn_reservation "falkor_fpmsc_3_gtov" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_mcr")) + "falkor_gtov") + +(define_insn_reservation "falkor_fpmsc_1_vxvy" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "fmov,fconsts,fconstd")) + "falkor_vxvy") + +;; No separate type for float-to-fixed conversions. Same type as +;; float-to-int conversions. They schedule the same though, so no problem. + +(define_insn_reservation "falkor_fpmsc_6_gtov" 6 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "f_cvti2f")) + "falkor_gtov") + +;; Load Instructions + +(define_insn_reservation "falkor_ld_3_ld" 3 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "load1,load2")) + "falkor_ld") + +;; Miscellaneous Data-Processing Instructions + +(define_insn_reservation "falkor_misc_1_xyz" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "bfx,bfm,extend,rotate_imm,shift_imm")) + "falkor_xyz") + +(define_insn_reservation "falkor_misc_2_x" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "crc")) + "falkor_x") + +(define_insn_reservation "falkor_misc_2_xyz" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "clz,rbit,rev")) + "falkor_xyz") + +;; Divide and Multiply Instructions + +(define_insn_reservation "falkor_muldiv_4_x_mul" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "mul")) + "falkor_x") + +(define_insn_reservation "falkor_muldiv_4_x_mla" 4 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "mla,smlal,umlal")) + "falkor_x") + +(define_insn_reservation "falkor_muldiv_5_x_mul" 5 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "smull,umull")) + "falkor_x") + +(define_insn_reservation "falkor_md_11_x_z" 11 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "sdiv,udiv")) + "falkor_x+falkor_z") + +;; Move and Shift Instructions + +(define_insn_reservation "falkor_mvs_1_xyz" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "mov_imm,shift_reg")) + "falkor_xyz") + +(define_insn_reservation "falkor_mvs_1_xyzb" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "adr")) + "falkor_xyzb") + +;; Other Instructions + +;; Block is for instruction scheduling blockage insns in RTL. There are no +;; hardware instructions emitted for them, so don't use any resources. + +(define_insn_reservation "falkor_other_0_nothing" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "no_insn,trap,block")) + "nothing") + +(define_insn_reservation "falkor_other_2_z" 2 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "mrs")) + "falkor_z") + +;; Assume multiple instructions use all pipes. + +(define_insn_reservation "falkor_extra" 1 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "multiple")) + "falkor_x+falkor_y+falkor_z+falkor_b+falkor_vx+falkor_vy+falkor_ld+falkor_st+falkor_sd+falkor_vsd+falkor_gtov+falkor_vtog") + +;; Store Instructions + +;; No use of store_rel, store3, or store4 in aarch64. + +(define_insn_reservation "falkor_st_0_st_sd" 0 + (and (eq_attr "tune" "falkor") + (eq_attr "type" "store1,store2")) + "falkor_st+falkor_sd") + +;; Muliply bypasses. + +;; 1 cycle latency (0 bubble) for an integer mul or mac feeding into a mac. + +(define_bypass 1 + "falkor_ai_4_vxvy_mul,falkor_ai_4_vxvy_mla,falkor_ai_4_vxvy_vxvy_mul,falkor_ai_4_vxvy_vxvy_mla,falkor_muldiv_4_x_mul,falkor_muldiv_4_x_mla,falkor_muldiv_5_x_mul" + "falkor_ai_4_vxvy_mla,falkor_ai_4_vxvy_vxvy_mla,falkor_muldiv_4_x_mla") + +;; 3 cycle latency (2 bubbles) for an FP mul or mac feeding into a mac. + +(define_bypass 3 + "falkor_afp_5_vxvy_mul,falkor_afp_5_vxvy_mla,falkor_afp_5_vxvy_vxvy_mul,falkor_afp_5_vxvy_vxvy_mla,falkor_afp_6_vxvy_mul,falkor_afp_6_vxvy_mla,falkor_afp_6_vxvy_vxvy_mul,falkor_afp_6_vxvy_vxvy_mla,falkor_fpdt_5_vxvy_mul,falkor_fpdt_5_vxvy_mla,falkor_fpdt_6_vxvy_mul,falkor_fpdt_6_vxvy_mla" + "falkor_afp_5_vxvy_mla,falkor_afp_5_vxvy_vxvy_mla,falkor_afp_6_vxvy_mla,falkor_afp_6_vxvy_vxvy_mla,falkor_fpdt_5_vxvy_mla,falkor_fpdt_6_vxvy_mla") diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 067cef785331a..cceb57525c7aa 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -523,6 +523,17 @@ (SI "SI") (HI "HI") (QI "QI")]) +;; Define element mode for each vector mode (lower case). +(define_mode_attr Vel [(V8QI "qi") (V16QI "qi") + (V4HI "hi") (V8HI "hi") + (V2SI "si") (V4SI "si") + (DI "di") (V2DI "di") + (V4HF "hf") (V8HF "hf") + (V2SF "sf") (V4SF "sf") + (V2DF "df") (DF "df") + (SI "si") (HI "hi") + (QI "qi")]) + ;; 64-bit container modes the inner or scalar source mode. (define_mode_attr VCOND [(HI "V4HI") (SI "V2SI") (V4HI "V4HI") (V8HI "V4HI") diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 95d28cfa33c6e..11243c4ce00aa 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -57,11 +57,6 @@ (ior (match_operand 0 "register_operand") (match_test "op == const0_rtx")))) -(define_predicate "aarch64_reg_or_fp_float" - (ior (match_operand 0 "register_operand") - (and (match_code "const_double") - (match_test "aarch64_float_const_rtx_p (op)")))) - (define_predicate "aarch64_reg_or_fp_zero" (ior (match_operand 0 "register_operand") (and (match_code "const_double") diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 9f5dae290546e..e13c5f9fc5738 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -26,6 +26,8 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "memmodel.h" #include "gimple.h" #include "df.h" @@ -9456,6 +9458,25 @@ And in the noreturn case: if (current_function_has_exception_handlers ()) alpha_pad_function_end (); + + /* CALL_PAL that implements trap insn, updates program counter to point + after the insn. In case trap is the last insn in the function, + emit NOP to guarantee that PC remains inside function boundaries. + This workaround is needed to get reliable backtraces. */ + + rtx_insn *insn = prev_active_insn (get_last_insn ()); + + if (insn && NONJUMP_INSN_P (insn)) + { + rtx pat = PATTERN (insn); + if (GET_CODE (pat) == PARALLEL) + { + rtx vec = XVECEXP (pat, 0, 0); + if (GET_CODE (vec) == TRAP_IF + && XEXP (vec, 0) == const1_rtx) + emit_insn_after (gen_unop (), insn); + } + } } static void diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index be5f1bd200378..057f8756fba88 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 25677d19e2052..3d15a8185a741 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -32,6 +32,7 @@ #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -143,8 +144,8 @@ static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); #endif static tree arm_handle_cmse_nonsecure_entry (tree *, tree, tree, int, bool *); static tree arm_handle_cmse_nonsecure_call (tree *, tree, tree, int, bool *); -static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT); -static void arm_output_function_prologue (FILE *, HOST_WIDE_INT); +static void arm_output_function_epilogue (FILE *); +static void arm_output_function_prologue (FILE *); static int arm_comp_type_attributes (const_tree, const_tree); static void arm_set_default_type_attributes (tree); static int arm_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int); @@ -19698,7 +19699,7 @@ arm_poke_function_name (FILE *stream, const char *name) /* Place some comments into the assembler stream describing the current function. */ static void -arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size) +arm_output_function_prologue (FILE *f) { unsigned long func_type; @@ -19741,7 +19742,8 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size) asm_fprintf (f, "\t%@ args = %d, pretend = %d, frame = %wd\n", crtl->args.size, - crtl->args.pretend_args_size, frame_size); + crtl->args.pretend_args_size, + (HOST_WIDE_INT) get_frame_size ()); asm_fprintf (f, "\t%@ frame_needed = %d, uses_anonymous_args = %d\n", frame_pointer_needed, @@ -19756,8 +19758,7 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size) } static void -arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, - HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED) +arm_output_function_epilogue (FILE *) { arm_stack_offsets *offsets; diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 48992879a8eec..7acbaf1bb40a4 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -444,6 +444,14 @@ (V2SF "SF") (V4SF "SF") (DI "DI") (V2DI "DI")]) +;; As above but in lower case. +(define_mode_attr V_elem_l [(V8QI "qi") (V16QI "qi") + (V4HI "hi") (V8HI "hi") + (V4HF "hf") (V8HF "hf") + (V2SI "si") (V4SI "si") + (V2SF "sf") (V4SF "sf") + (DI "di") (V2DI "di")]) + ;; Element modes for vector extraction, padded up to register size. (define_mode_attr V_ext [(V8QI "SI") (V16QI "SI") diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md index 235c46da1a197..45b3bd18052dd 100644 --- a/gcc/config/arm/neon.md +++ b/gcc/config/arm/neon.md @@ -412,7 +412,7 @@ DONE; }) -(define_insn "vec_extract" +(define_insn "vec_extract" [(set (match_operand: 0 "nonimmediate_operand" "=Um,r") (vec_select: (match_operand:VD_LANE 1 "s_register_operand" "w,w") @@ -434,7 +434,7 @@ [(set_attr "type" "neon_store1_one_lane,neon_to_gp")] ) -(define_insn "vec_extract" +(define_insn "vec_extract" [(set (match_operand: 0 "nonimmediate_operand" "=Um,r") (vec_select: (match_operand:VQ2 1 "s_register_operand" "w,w") @@ -460,7 +460,7 @@ [(set_attr "type" "neon_store1_one_lane,neon_to_gp")] ) -(define_insn "vec_extractv2di" +(define_insn "vec_extractv2didi" [(set (match_operand:DI 0 "nonimmediate_operand" "=Um,r") (vec_select:DI (match_operand:V2DI 1 "s_register_operand" "w,w") @@ -479,7 +479,7 @@ [(set_attr "type" "neon_store1_one_lane_q,neon_to_gp_q")] ) -(define_expand "vec_init" +(define_expand "vec_init" [(match_operand:VDQ 0 "s_register_operand" "") (match_operand 1 "" "")] "TARGET_NEON" @@ -1581,7 +1581,7 @@ neon_pairwise_reduce (vec, operands[1], mode, &gen_neon_vpadd_internal); /* The same result is actually computed into every element. */ - emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); DONE; }) @@ -1607,7 +1607,7 @@ rtx vec = gen_reg_rtx (V2DImode); emit_insn (gen_arm_reduc_plus_internal_v2di (vec, operands[1])); - emit_insn (gen_vec_extractv2di (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extractv2didi (operands[0], vec, const0_rtx)); DONE; }) @@ -1631,7 +1631,7 @@ neon_pairwise_reduce (vec, operands[1], mode, &gen_neon_vpsmin); /* The result is computed into every element of the vector. */ - emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); DONE; }) @@ -1658,7 +1658,7 @@ neon_pairwise_reduce (vec, operands[1], mode, &gen_neon_vpsmax); /* The result is computed into every element of the vector. */ - emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); DONE; }) @@ -1685,7 +1685,7 @@ neon_pairwise_reduce (vec, operands[1], mode, &gen_neon_vpumin); /* The result is computed into every element of the vector. */ - emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); DONE; }) @@ -1711,7 +1711,7 @@ neon_pairwise_reduce (vec, operands[1], mode, &gen_neon_vpumax); /* The result is computed into every element of the vector. */ - emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], vec, const0_rtx)); DONE; }) @@ -3272,7 +3272,8 @@ } if (GET_MODE_UNIT_BITSIZE (mode) == 32) - emit_insn (gen_vec_extract (operands[0], operands[1], operands[2])); + emit_insn (gen_vec_extract (operands[0], operands[1], + operands[2])); else emit_insn (gen_neon_vget_lane_sext_internal (operands[0], operands[1], @@ -3301,7 +3302,8 @@ } if (GET_MODE_UNIT_BITSIZE (mode) == 32) - emit_insn (gen_vec_extract (operands[0], operands[1], operands[2])); + emit_insn (gen_vec_extract (operands[0], operands[1], + operands[2])); else emit_insn (gen_neon_vget_lane_zext_internal (operands[0], operands[1], diff --git a/gcc/config/arm/t-vxworks b/gcc/config/arm/t-vxworks index 093d7fae88b07..0a3840ba8fee0 100644 --- a/gcc/config/arm/t-vxworks +++ b/gcc/config/arm/t-vxworks @@ -16,9 +16,7 @@ # along with GCC; see the file COPYING3. If not see # . -MULTILIB_OPTIONS = \ - mrtp fPIC \ - t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/tstrongarm/txscale/txscalebe -MULTILIB_MATCHES = fPIC=fpic -# Don't build -fPIC multilibs for kernel or Thumb code. -MULTILIB_EXCEPTIONS = fPIC* mrtp/fPIC/*t[45]t* +MULTILIB_OPTIONS = mrtp fPIC + +# -fPIC alone is not supported, only together with -mrtp +MULTILIB_EXCEPTIONS = fPIC diff --git a/gcc/config/arm/vxworks.h b/gcc/config/arm/vxworks.h index f20324f144d97..59f6282a0ea78 100644 --- a/gcc/config/arm/vxworks.h +++ b/gcc/config/arm/vxworks.h @@ -26,7 +26,15 @@ a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ +/* TARGET_OS_CPP_BUILTINS, down to BPABI if defined. */ +#if defined (TARGET_BPABI_CPP_BUILTINS) +#define MAYBE_TARGET_BPABI_CPP_BUILTINS TARGET_BPABI_CPP_BUILTINS +#else +#define MAYBE_TARGET_BPABI_CPP_BUILTINS() +#endif + +#undef TARGET_OS_CPP_BUILTINS #define TARGET_OS_CPP_BUILTINS() \ do { \ if (TARGET_BIG_END) \ @@ -36,8 +44,29 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see \ if (arm_arch_xscale) \ builtin_define ("CPU=XSCALE"); \ + else if (arm_arch7) \ + { \ + if (!arm_arch_notm) \ + builtin_define ("CPU=ARMARCH7M"); \ + else if (TARGET_THUMB) \ + builtin_define ("CPU=ARMARCH7_T2"); \ + else \ + builtin_define ("CPU=ARMARCH7"); \ + } \ + else if (arm_arch6) \ + { \ + if (TARGET_THUMB) \ + builtin_define ("CPU=ARMARCH6_T"); \ + else \ + builtin_define ("CPU=ARMARCH6"); \ + } \ else if (arm_arch5) \ - builtin_define ("CPU=ARMARCH5"); \ + { \ + if (TARGET_THUMB) \ + builtin_define ("CPU=ARMARCH5_T"); \ + else \ + builtin_define ("CPU=ARMARCH5"); \ + } \ else if (arm_arch4) \ { \ if (TARGET_THUMB) \ @@ -46,6 +75,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see builtin_define ("CPU=ARMARCH4"); \ } \ VXWORKS_OS_CPP_BUILTINS (); \ + MAYBE_TARGET_BPABI_CPP_BUILTINS (); \ } while (0) #undef SUBTARGET_OVERRIDE_OPTIONS @@ -55,27 +85,32 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef SUBTARGET_CPP_SPEC #define SUBTARGET_CPP_SPEC "-D__ELF__" VXWORKS_ADDITIONAL_CPP_SPEC +/* .text.hot and .text.unlikely sections are badly handled by the + VxWorks kernel mode loader for ARM style exceptions. */ + +#if ARM_UNWIND_INFO +#define EXTRA_CC1_SPEC "%{!mrtp:-fno-reorder-functions}" +#else +#define EXTRA_CC1_SPEC +#endif + #undef CC1_SPEC -#define CC1_SPEC \ -"%{tstrongarm:-mlittle-endian -mcpu=strongarm ; \ - t4: -mlittle-endian -march=armv4 ; \ - t4be: -mbig-endian -march=armv4 ; \ - t4t: -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ; \ - t4tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv4t ; \ - t5: -mlittle-endian -march=armv5 ; \ - t5be: -mbig-endian -march=armv5 ; \ - t5t: -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ; \ - t5tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv5 ; \ - txscale: -mlittle-endian -mcpu=xscale ; \ - txscalebe: -mbig-endian -mcpu=xscale ; \ - : -march=armv4}" - -/* Pass -EB for big-endian targets. */ -#define VXWORKS_ENDIAN_SPEC \ - "%{mbig-endian|t4be|t4tbe|t5be|t5tbe|txscalebe:-EB}" +#define CC1_SPEC "" EXTRA_CC1_SPEC + +/* Translate an explicit -mbig-endian as an explicit -EB to assembler + and linker, and pass abi options matching the target expectations + or command-line requests. */ +#define VXWORKS_ENDIAN_SPEC "%{mbig-endian:-EB}" + +#if defined (TARGET_BPABI_CPP_BUILTINS) +#define MAYBE_ASM_ABI_SPEC \ + "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=5}" TARGET_FIX_V4BX_SPEC +#else +#define MAYBE_ASM_ABI_SPEC +#endif #undef SUBTARGET_EXTRA_ASM_SPEC -#define SUBTARGET_EXTRA_ASM_SPEC VXWORKS_ENDIAN_SPEC +#define SUBTARGET_EXTRA_ASM_SPEC MAYBE_ASM_ABI_SPEC " " VXWORKS_ENDIAN_SPEC #undef LINK_SPEC #define LINK_SPEC VXWORKS_LINK_SPEC " " VXWORKS_ENDIAN_SPEC @@ -89,6 +124,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef ENDFILE_SPEC #define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC +/* For exceptions, pre VX7 uses DWARF2 info, VX7 uses ARM unwinding. */ +#undef DWARF2_UNWIND_INFO +#define DWARF2_UNWIND_INFO (!TARGET_VXWORKS7) + +#undef ARM_TARGET2_DWARF_FORMAT +#define ARM_TARGET2_DWARF_FORMAT \ + (TARGET_VXWORKS_RTP ? DW_EH_PE_pcrel : DW_EH_PE_absptr) + /* There is no default multilib. */ #undef MULTILIB_DEFAULTS diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 1f333ccc1b2dc..c91f6c485c32d 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -26,6 +26,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "cgraph.h" #include "c-family/c-common.h" #include "cfghooks.h" @@ -775,7 +777,7 @@ avr_option_override (void) warning (OPT_fPIE, "-fPIE is not supported"); #if !defined (HAVE_AS_AVR_MGCCISR_OPTION) - TARGET_GASISR_PROLOGUES = 0; + avr_gasisr_prologues = 0; #endif if (!avr_set_core_architecture()) @@ -1109,7 +1111,7 @@ avr_set_current_function (tree decl) || 0 == strcmp ("INTERRUPT", name) || 0 == strcmp ("SIGNAL", name)) { - warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved indentifier" + warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier" " in AVR-LibC. Consider %<#include %>" " before using the %qs macro", name, name); } @@ -1457,7 +1459,7 @@ class avr_pass_pre_proep : public rtl_opt_pass virtual unsigned int execute (function *fun) { - if (TARGET_GASISR_PROLOGUES + if (avr_gasisr_prologues // Whether this function is an ISR worth scanning at all. && !fun->machine->is_no_gccisr && (fun->machine->is_interrupt @@ -9788,10 +9790,12 @@ avr_handle_addr_attribute (tree *node, tree name, tree args, bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0); location_t loc = DECL_SOURCE_LOCATION (*node); - if (TREE_CODE (*node) != VAR_DECL) + if (!VAR_P (*node)) { - warning_at (loc, 0, "%qE attribute only applies to variables", name); + warning_at (loc, OPT_Wattributes, "%qE attribute only applies to " + "variables", name); *no_add = true; + return NULL_TREE; } if (args != NULL_TREE) @@ -9801,8 +9805,8 @@ avr_handle_addr_attribute (tree *node, tree name, tree args, tree arg = TREE_VALUE (args); if (TREE_CODE (arg) != INTEGER_CST) { - warning (0, "%qE attribute allows only an integer constant argument", - name); + warning_at (loc, OPT_Wattributes, "%qE attribute allows only an " + "integer constant argument", name); *no_add = true; } else if (io_p @@ -9811,19 +9815,20 @@ avr_handle_addr_attribute (tree *node, tree name, tree args, ? low_io_address_operand : io_address_operand) (GEN_INT (TREE_INT_CST_LOW (arg)), QImode))) { - warning_at (loc, 0, "%qE attribute address out of range", name); + warning_at (loc, OPT_Wattributes, "%qE attribute address " + "out of range", name); *no_add = true; } else { tree attribs = DECL_ATTRIBUTES (*node); - const char *names[] = { "io", "io_low", "address", NULL } ; + const char *names[] = { "io", "io_low", "address", NULL }; for (const char **p = names; *p; p++) { tree other = lookup_attribute (*p, attribs); if (other && TREE_VALUE (other)) { - warning_at (loc, 0, + warning_at (loc, OPT_Wattributes, "both %s and %qE attribute provide address", *p, name); *no_add = true; @@ -9834,7 +9839,8 @@ avr_handle_addr_attribute (tree *node, tree name, tree args, } if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node)) - warning_at (loc, 0, "%qE attribute on non-volatile variable", name); + warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable", + name); return NULL_TREE; } @@ -9884,11 +9890,11 @@ avr_attribute_table[] = false }, { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute, false }, - { "io", 0, 1, false, false, false, avr_handle_addr_attribute, + { "io", 0, 1, true, false, false, avr_handle_addr_attribute, false }, - { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute, + { "io_low", 0, 1, true, false, false, avr_handle_addr_attribute, false }, - { "address", 1, 1, false, false, false, avr_handle_addr_attribute, + { "address", 1, 1, true, false, false, avr_handle_addr_attribute, false }, { "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute, false }, diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index d17c0b1364074..fe5ca303ef77a 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -5819,7 +5819,7 @@ (set (match_dup 2) (unspec_volatile:BLK [(match_dup 2)] UNSPECV_MEMORY_BARRIER))])] - "TARGET_GASISR_PROLOGUES" + "avr_gasisr_prologues" { operands[2] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); MEM_VOLATILE_P (operands[2]) = 1; @@ -5833,7 +5833,7 @@ (unspec_volatile:HI [(reg:HI REG_SP)] UNSPECV_GASISR)) (set (match_operand:BLK 2) (unspec_volatile:BLK [(match_dup 2)] UNSPECV_MEMORY_BARRIER))] - "TARGET_GASISR_PROLOGUES" + "avr_gasisr_prologues" "__gcc_isr %0" [(set_attr "length" "6,5") (set_attr "cc" "clobber")]) diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt index 81850e037f61d..72955014107ec 100644 --- a/gcc/config/avr/avr.opt +++ b/gcc/config/avr/avr.opt @@ -27,7 +27,7 @@ Target RejectNegative Joined Var(avr_mmcu) MissingArgError(missing device or arc -mmcu=MCU Select the target MCU. mgas-isr-prologues -Target Report Mask(GASISR_PROLOGUES) +Target Report Var(avr_gasisr_prologues) UInteger Init(0) Allow usage of __gcc_isr pseudo instructions in ISR prologues and epilogues. mn-flash= diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 9fe90fc37b449..f04fe8747777d 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "cfghooks.h" #include "df.h" #include "memmodel.h" diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c index 4529fd44aae5c..a7083c12898b2 100644 --- a/gcc/config/c6x/c6x.c +++ b/gcc/config/c6x/c6x.c @@ -32,6 +32,7 @@ #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c index 93edd232af25b..ab6ef7adf1d6c 100644 --- a/gcc/config/cr16/cr16.c +++ b/gcc/config/cr16/cr16.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 8c134a6bc8b20..b57881ac04e8d 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "cfghooks.h" #include "df.h" #include "memmodel.h" diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 9a8cf31d400bd..b6dad70df0ab5 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "insn-config.h" #include "emit-rtl.h" #include "cgraph.h" @@ -1959,7 +1960,8 @@ darwin_asm_lto_end (void) } static void -darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl); +darwin_asm_dwarf_section (const char *name, unsigned int flags, + tree decl, bool is_for_lto); /* Called for the TARGET_ASM_NAMED_SECTION hook. */ @@ -2001,7 +2003,9 @@ darwin_asm_named_section (const char *name, vec_safe_push (lto_section_names, e); } else if (strncmp (name, "__DWARF,", 8) == 0) - darwin_asm_dwarf_section (name, flags, decl); + darwin_asm_dwarf_section (name, flags, decl, false); + else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0) + darwin_asm_dwarf_section (name, flags, decl, true); else fprintf (asm_out_file, "\t.section %s\n", name); } @@ -2783,19 +2787,37 @@ static GTY (()) vec *dwarf_sect_names_table; static void darwin_asm_dwarf_section (const char *name, unsigned int flags, - tree ARG_UNUSED (decl)) + tree ARG_UNUSED (decl), bool is_for_lto) { unsigned i; - int namelen; - const char * sname; + int namelen, extra = 0; + const char *sect, *lto_add = ""; + char sname[64]; dwarf_sect_used_entry *ref; bool found = false; - gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED)) - == (SECTION_DEBUG | SECTION_NAMED)); - /* We know that the name starts with __DWARF, */ - sname = name + 8; - namelen = strchr (sname, ',') - sname; - gcc_assert (namelen); + + gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED)) + == (SECTION_DEBUG | SECTION_NAMED)); + + /* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO */ + sect = strchr (name, ',') + 1; + namelen = strchr (sect, ',') - sect; + gcc_checking_assert (namelen); + + /* The section switch is output as written... */ + fprintf (asm_out_file, "\t.section %s\n", name); + + /* ... but the string we keep to make section start labels needs + adjustment for lto cases. */ + if (is_for_lto) + { + lto_add = "_lto"; + extra = 4; + } + + snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add); + namelen += extra; + if (dwarf_sect_names_table == NULL) vec_alloc (dwarf_sect_names_table, 16); else @@ -2813,7 +2835,6 @@ darwin_asm_dwarf_section (const char *name, unsigned int flags, } } - fprintf (asm_out_file, "\t.section %s\n", name); if (!found) { dwarf_sect_used_entry e; @@ -2866,14 +2887,24 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab, HOST_WIDE_INT offset, section *base) { char sname[64]; - int namelen; + int namelen, extra = 0; + bool is_for_lto; + const char *lto_add = ""; - gcc_assert (base->common.flags & SECTION_NAMED); - gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0); - gcc_assert (strchr (base->named.name + 8, ',')); + gcc_checking_assert (base->common.flags & SECTION_NAMED); + is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0; + gcc_checking_assert (is_for_lto + || strncmp (base->named.name, "__DWARF,", 8) == 0); + const char *name = strchr (base->named.name, ',') + 1; + gcc_checking_assert (name); - namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8); - sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8); + namelen = strchr (name, ',') - (name); + if (is_for_lto) + { + lto_add = "_lto"; + extra = 4; + } + snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add); darwin_asm_output_dwarf_delta (file, size, lab, sname, offset); } diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index a8397cd233187..6cec8deb8cdb0 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -445,7 +445,14 @@ extern GTY(()) int darwin_ms_struct; #define DEBUG_PUBTYPES_SECTION "__DWARF,__debug_pubtypes,regular,debug" #define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug" #define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug" -#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug" +#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug" + +#define DEBUG_LTO_INFO_SECTION "__GNU_DWARF_LTO,__debug_info,regular,debug" +#define DEBUG_LTO_ABBREV_SECTION "__GNU_DWARF_LTO,__debug_abbrev,regular,debug" +#define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug" +#define DEBUG_LTO_LINE_SECTION "__GNU_DWARF_LTO,__debug_line,regular,debug" +#define DEBUG_LTO_STR_SECTION "__GNU_DWARF_LTO,__debug_str,regular,debug" +#define DEBUG_LTO_MACRO_SECTION "__GNU_DWARF_LTO,__debug_macro,regular,debug" #define TARGET_WANT_DEBUG_PUB_SECTIONS true diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index b9ec0f40d12ab..4e27557d3ce98 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "emit-rtl.h" #include "recog.h" diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c index 42bec9f733c2b..d83b2f31daa6a 100644 --- a/gcc/config/fr30/fr30.c +++ b/gcc/config/fr30/fr30.c @@ -27,6 +27,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "emit-rtl.h" diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index c571d63f2c667..2697ba978dff2 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -347,8 +348,8 @@ static void frv_reorg_packet (void); static void frv_register_nop (rtx); static void frv_reorg (void); static void frv_pack_insns (void); -static void frv_function_prologue (FILE *, HOST_WIDE_INT); -static void frv_function_epilogue (FILE *, HOST_WIDE_INT); +static void frv_function_prologue (FILE *); +static void frv_function_epilogue (FILE *); static bool frv_assemble_integer (rtx, unsigned, int); static void frv_init_builtins (void); static rtx frv_expand_builtin (tree, rtx, rtx, machine_mode, int); @@ -1400,7 +1401,7 @@ frv_function_contains_far_jump (void) will return correctly. It also does the VLIW packing. */ static void -frv_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +frv_function_prologue (FILE *file) { rtx_insn *insn, *next, *last_call; @@ -1840,8 +1841,7 @@ frv_expand_prologue (void) this function provides a convenient place to do cleanup. */ static void -frv_function_epilogue (FILE *file ATTRIBUTE_UNUSED, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +frv_function_epilogue (FILE *) { frv_stack_cache = (frv_stack_t *)0; diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c index db0365e92c1fa..78c5edc8f0986 100644 --- a/gcc/config/ft32/ft32.c +++ b/gcc/config/ft32/ft32.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index 2787a3d16be9e..de605b0c46657 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h @@ -50,19 +50,28 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #if defined HAVE_LD_PIE #define GNU_USER_TARGET_STARTFILE_SPEC \ - "%{!shared: %{pg|p|profile:gcrt1.o%s;: \ - %{" PIE_SPEC ":Scrt1.o%s} %{" NO_PIE_SPEC ":crt1.o%s}}} \ - crti.o%s %{static:crtbeginT.o%s;: %{shared:crtbeginS.o%s} \ - %{" PIE_SPEC ":crtbeginS.o%s} \ - %{" NO_PIE_SPEC ":crtbegin.o%s}} \ + "%{shared:; \ + pg|p|profile:gcrt1.o%s; \ + static:crt1.o%s; \ + " PIE_SPEC ":Scrt1.o%s; \ + :crt1.o%s} \ + crti.o%s \ + %{static:crtbeginT.o%s; \ + shared|" PIE_SPEC ":crtbeginS.o%s; \ + :crtbegin.o%s} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ fvtable-verify=std:vtv_start.o%s} \ " CRTOFFLOADBEGIN #else #define GNU_USER_TARGET_STARTFILE_SPEC \ - "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ - crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ + "%{shared:; \ + pg|p|profile:gcrt1.o%s; \ + :crt1.o%s} \ + crti.o%s \ + %{static:crtbeginT.o%s; \ + shared|pie:crtbeginS.o%s; \ + :crtbegin.o%s} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ fvtable-verify=std:vtv_start.o%s} \ @@ -82,15 +91,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see "%{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_end_preinit.o%s; \ fvtable-verify=std:vtv_end.o%s} \ - %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \ - %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s \ + %{static:crtend.o%s; \ + shared|" PIE_SPEC ":crtendS.o%s; \ + :crtend.o%s} \ + crtn.o%s \ " CRTOFFLOADEND #else #define GNU_USER_TARGET_ENDFILE_SPEC \ "%{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_end_preinit.o%s; \ fvtable-verify=std:vtv_end.o%s} \ - %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s \ + %{static:crtend.o%s; \ + shared|pie:crtendS.o%s; \ + :crtend.o%s} \ + crtn.o%s \ " CRTOFFLOADEND #endif #undef ENDFILE_SPEC diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index acdededeccc7e..0e0bb57768d4f 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" diff --git a/gcc/config/i386/cygming.opt b/gcc/config/i386/cygming.opt index 2d7c7d2b67496..abe5932104071 100644 --- a/gcc/config/i386/cygming.opt +++ b/gcc/config/i386/cygming.opt @@ -50,6 +50,10 @@ muse-libstdc-wrappers Target Condition({defined (USE_CYGWIN_LIBSTDCXX_WRAPPERS)}) Compile code that relies on Cygwin DLL wrappers to support C++ operator new/delete replacement. +fset-stack-executable +Common Report Var(flag_setstackexecutable) Init(1) Optimization +For nested functions on stack executable permission is set. + posix Driver diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h index a4683b4662e7f..7e34bb799c336 100644 --- a/gcc/config/i386/cygwin.h +++ b/gcc/config/i386/cygwin.h @@ -153,3 +153,7 @@ along with GCC; see the file COPYING3. If not see #endif #define LIBGCC_SONAME "cyggcc_s" LIBGCC_EH_EXTN "-1.dll" +/* Make stack executable to avoid DEP problems with trampolines. */ +#define HAVE_ENABLE_EXECUTE_STACK +#undef CHECK_EXECUTE_STACK_ENABLED +#define CHECK_EXECUTE_STACK_ENABLED flag_setstackexecutable diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index e91468a1a2ec2..6ce90748e38d1 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -852,36 +852,36 @@ BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_mulv2siv2di3, "__builtin_ia32_pmu BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_mulv4si3, "__builtin_ia32_pmulld128", IX86_BUILTIN_PMULLD128, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI) /* SSE4.1 */ -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_roundpd", IX86_BUILTIN_ROUNDPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_INT) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_roundps", IX86_BUILTIN_ROUNDPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_INT) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundsd, "__builtin_ia32_roundsd", IX86_BUILTIN_ROUNDSD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundss, "__builtin_ia32_roundss", IX86_BUILTIN_ROUNDSS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_roundpd", IX86_BUILTIN_ROUNDPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_INT) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps, "__builtin_ia32_roundps", IX86_BUILTIN_ROUNDPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_INT) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundsd, "__builtin_ia32_roundsd", IX86_BUILTIN_ROUNDSD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundss, "__builtin_ia32_roundss", IX86_BUILTIN_ROUNDSS, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_INT) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_floorpd", IX86_BUILTIN_FLOORPD, (enum rtx_code) ROUND_FLOOR, (int) V2DF_FTYPE_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_ceilpd", IX86_BUILTIN_CEILPD, (enum rtx_code) ROUND_CEIL, (int) V2DF_FTYPE_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_truncpd", IX86_BUILTIN_TRUNCPD, (enum rtx_code) ROUND_TRUNC, (int) V2DF_FTYPE_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_rintpd", IX86_BUILTIN_RINTPD, (enum rtx_code) ROUND_MXCSR, (int) V2DF_FTYPE_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_floorpd", IX86_BUILTIN_FLOORPD, (enum rtx_code) ROUND_FLOOR, (int) V2DF_FTYPE_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_ceilpd", IX86_BUILTIN_CEILPD, (enum rtx_code) ROUND_CEIL, (int) V2DF_FTYPE_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_truncpd", IX86_BUILTIN_TRUNCPD, (enum rtx_code) ROUND_TRUNC, (int) V2DF_FTYPE_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd, "__builtin_ia32_rintpd", IX86_BUILTIN_RINTPD, (enum rtx_code) ROUND_MXCSR, (int) V2DF_FTYPE_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_floorpd_vec_pack_sfix", IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_ceilpd_vec_pack_sfix", IX86_BUILTIN_CEILPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_floorpd_vec_pack_sfix", IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundpd_vec_pack_sfix, "__builtin_ia32_ceilpd_vec_pack_sfix", IX86_BUILTIN_CEILPD_VEC_PACK_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V2DF_V2DF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_roundv2df2, "__builtin_ia32_roundpd_az", IX86_BUILTIN_ROUNDPD_AZ, UNKNOWN, (int) V2DF_FTYPE_V2DF) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_roundv2df2_vec_pack_sfix, "__builtin_ia32_roundpd_az_vec_pack_sfix", IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX, UNKNOWN, (int) V4SI_FTYPE_V2DF_V2DF) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_roundv2df2, "__builtin_ia32_roundpd_az", IX86_BUILTIN_ROUNDPD_AZ, UNKNOWN, (int) V2DF_FTYPE_V2DF) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_roundv2df2_vec_pack_sfix, "__builtin_ia32_roundpd_az_vec_pack_sfix", IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX, UNKNOWN, (int) V4SI_FTYPE_V2DF_V2DF) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_floorps", IX86_BUILTIN_FLOORPS, (enum rtx_code) ROUND_FLOOR, (int) V4SF_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_ceilps", IX86_BUILTIN_CEILPS, (enum rtx_code) ROUND_CEIL, (int) V4SF_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_truncps", IX86_BUILTIN_TRUNCPS, (enum rtx_code) ROUND_TRUNC, (int) V4SF_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps, "__builtin_ia32_rintps", IX86_BUILTIN_RINTPS, (enum rtx_code) ROUND_MXCSR, (int) V4SF_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps, "__builtin_ia32_floorps", IX86_BUILTIN_FLOORPS, (enum rtx_code) ROUND_FLOOR, (int) V4SF_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps, "__builtin_ia32_ceilps", IX86_BUILTIN_CEILPS, (enum rtx_code) ROUND_CEIL, (int) V4SF_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps, "__builtin_ia32_truncps", IX86_BUILTIN_TRUNCPS, (enum rtx_code) ROUND_TRUNC, (int) V4SF_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps, "__builtin_ia32_rintps", IX86_BUILTIN_RINTPS, (enum rtx_code) ROUND_MXCSR, (int) V4SF_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_floorps_sfix", IX86_BUILTIN_FLOORPS_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_ceilps_sfix", IX86_BUILTIN_CEILPS_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_floorps_sfix", IX86_BUILTIN_FLOORPS_SFIX, (enum rtx_code) ROUND_FLOOR, (int) V4SI_FTYPE_V4SF_ROUND) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_roundps_sfix, "__builtin_ia32_ceilps_sfix", IX86_BUILTIN_CEILPS_SFIX, (enum rtx_code) ROUND_CEIL, (int) V4SI_FTYPE_V4SF_ROUND) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_roundv4sf2, "__builtin_ia32_roundps_az", IX86_BUILTIN_ROUNDPS_AZ, UNKNOWN, (int) V4SF_FTYPE_V4SF) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_roundv4sf2_sfix, "__builtin_ia32_roundps_az_sfix", IX86_BUILTIN_ROUNDPS_AZ_SFIX, UNKNOWN, (int) V4SI_FTYPE_V4SF) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_roundv4sf2, "__builtin_ia32_roundps_az", IX86_BUILTIN_ROUNDPS_AZ, UNKNOWN, (int) V4SF_FTYPE_V4SF) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_roundv4sf2_sfix, "__builtin_ia32_roundps_az_sfix", IX86_BUILTIN_ROUNDPS_AZ_SFIX, UNKNOWN, (int) V4SI_FTYPE_V4SF) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestz128", IX86_BUILTIN_PTESTZ, EQ, (int) INT_FTYPE_V2DI_V2DI_PTEST) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestc128", IX86_BUILTIN_PTESTC, LTU, (int) INT_FTYPE_V2DI_V2DI_PTEST) -BDESC (OPTION_MASK_ISA_ROUND, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestnzc128", IX86_BUILTIN_PTESTNZC, GTU, (int) INT_FTYPE_V2DI_V2DI_PTEST) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestz128", IX86_BUILTIN_PTESTZ, EQ, (int) INT_FTYPE_V2DI_V2DI_PTEST) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestc128", IX86_BUILTIN_PTESTC, LTU, (int) INT_FTYPE_V2DI_V2DI_PTEST) +BDESC (OPTION_MASK_ISA_SSE4_1, CODE_FOR_sse4_1_ptestv2di, "__builtin_ia32_ptestnzc128", IX86_BUILTIN_PTESTNZC, GTU, (int) INT_FTYPE_V2DI_V2DI_PTEST) /* SSE4.2 */ BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_gtv2di3, "__builtin_ia32_pcmpgtq", IX86_BUILTIN_PCMPGTQ, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index bf8a0492592d7..2c15ba8505cc1 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -201,6 +201,8 @@ extern void ix86_expand_truncdf_32 (rtx, rtx); extern void ix86_expand_vecop_qihi (enum rtx_code, rtx, rtx, rtx); +extern rtx ix86_split_stack_guard (void); + #ifdef TREE_CODE extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); #endif /* TREE_CODE */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 29a6dc3af2b7c..509fd3a26d5b7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -85,6 +85,9 @@ along with GCC; see the file COPYING3. If not see #include "print-rtl.h" #include "intl.h" #include "ifcvt.h" +#include "symbol-summary.h" +#include "ipa-prop.h" +#include "ipa-fnsummary.h" /* This file should be included last. */ #include "target-def.h" @@ -94,6 +97,7 @@ static rtx legitimize_pe_coff_extern_decl (rtx, bool); static rtx legitimize_pe_coff_symbol (rtx, bool); static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool); static bool ix86_save_reg (unsigned int, bool, bool); +static bool ix86_function_naked (const_tree); #ifndef CHECK_STACK_LIMIT #define CHECK_STACK_LIMIT (-1) @@ -2491,9 +2495,7 @@ class xlogue_layout { unsigned last_reg = m->call_ms2sysv_extra_regs + MIN_REGS - 1; gcc_assert (m->call_ms2sysv_extra_regs <= MAX_EXTRA_REGS); - return m_regs[last_reg].offset - + (m->call_ms2sysv_pad_out ? 8 : 0) - + STUB_INDEX_OFFSET; + return m_regs[last_reg].offset + STUB_INDEX_OFFSET; } /* Returns the offset for the base pointer used by the stub. */ @@ -5685,6 +5687,10 @@ ix86_option_override_internal (bool main_args_p, if (!opts_set->x_ix86_abi) opts->x_ix86_abi = DEFAULT_ABI; + if (opts->x_ix86_abi == MS_ABI && TARGET_X32_P (opts->x_ix86_isa_flags)) + error ("-mabi=ms not supported with X32 ABI"); + gcc_assert (opts->x_ix86_abi == SYSV_ABI || opts->x_ix86_abi == MS_ABI); + /* For targets using ms ABI enable ms-extensions, if not explicit turned off. For non-ms ABI we turn off this option. */ @@ -6314,7 +6320,7 @@ ix86_option_override_internal (bool main_args_p, } /* Set the default value for -mstackrealign. */ - if (opts->x_ix86_force_align_arg_pointer == -1) + if (!opts_set->x_ix86_force_align_arg_pointer) opts->x_ix86_force_align_arg_pointer = STACK_REALIGN_DEFAULT; ix86_default_incoming_stack_boundary = PREFERRED_STACK_BOUNDARY; @@ -6539,27 +6545,18 @@ ix86_option_override_internal (bool main_args_p, opts->x_target_flags |= MASK_CLD & ~opts_set->x_target_flags; #endif - if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && opts->x_flag_pic) + /* Set the default value for -mfentry. */ + if (!opts_set->x_flag_fentry) + opts->x_flag_fentry = TARGET_SEH; + else { - if (opts->x_flag_fentry > 0) - sorry ("-mfentry isn%'t supported for 32-bit in combination " + if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && opts->x_flag_pic + && opts->x_flag_fentry) + sorry ("-mfentry isn%'t supported for 32-bit in combination " "with -fpic"); - opts->x_flag_fentry = 0; - } - else if (TARGET_SEH) - { - if (opts->x_flag_fentry == 0) + else if (TARGET_SEH && !opts->x_flag_fentry) sorry ("-mno-fentry isn%'t compatible with SEH"); - opts->x_flag_fentry = 1; } - else if (opts->x_flag_fentry < 0) - { -#if defined(PROFILE_BEFORE_PROLOGUE) - opts->x_flag_fentry = 1; -#else - opts->x_flag_fentry = 0; -#endif - } if (TARGET_SEH && TARGET_CALL_MS2SYSV_XLOGUES) sorry ("-mcall-ms2sysv-xlogues isn%'t currently supported with SEH"); @@ -6652,17 +6649,74 @@ ix86_option_override_internal (bool main_args_p, gcc_assert ((opts->x_target_flags & MASK_LONG_DOUBLE_64) == 0 || (opts->x_target_flags & MASK_LONG_DOUBLE_128) == 0); - /* Save the initial options in case the user does function specific - options. */ - if (main_args_p) - target_option_default_node = target_option_current_node - = build_target_option_node (opts); - /* Handle stack protector */ if (!opts_set->x_ix86_stack_protector_guard) opts->x_ix86_stack_protector_guard = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS; +#ifdef TARGET_THREAD_SSP_OFFSET + ix86_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET; +#endif + + if (global_options_set.x_ix86_stack_protector_guard_offset_str) + { + char *endp; + const char *str = ix86_stack_protector_guard_offset_str; + + errno = 0; + int64_t offset; + +#if defined(INT64_T_IS_LONG) + offset = strtol (str, &endp, 0); +#else + offset = strtoll (str, &endp, 0); +#endif + + if (!*str || *endp || errno) + error ("%qs is not a valid number " + "in -mstack-protector-guard-offset=", str); + + if (!IN_RANGE (offset, HOST_WIDE_INT_C (-0x80000000), + HOST_WIDE_INT_C (0x7fffffff))) + error ("%qs is not a valid offset " + "in -mstack-protector-guard-offset=", str); + + ix86_stack_protector_guard_offset = offset; + } + + ix86_stack_protector_guard_reg = DEFAULT_TLS_SEG_REG; + + /* The kernel uses a different segment register for performance + reasons; a system call would not have to trash the userspace + segment register, which would be expensive. */ + if (ix86_cmodel == CM_KERNEL) + ix86_stack_protector_guard_reg = ADDR_SPACE_SEG_GS; + + if (global_options_set.x_ix86_stack_protector_guard_reg_str) + { + const char *str = ix86_stack_protector_guard_reg_str; + addr_space_t seg = ADDR_SPACE_GENERIC; + + /* Discard optional register prefix. */ + if (str[0] == '%') + str++; + + if (strlen (str) == 2 && str[1] == 's') + { + if (str[0] == 'f') + seg = ADDR_SPACE_SEG_FS; + else if (str[0] == 'g') + seg = ADDR_SPACE_SEG_GS; + } + + if (seg == ADDR_SPACE_GENERIC) + error ("%qs is not a valid base register " + "in -mstack-protector-guard-reg=", + ix86_stack_protector_guard_reg_str); + + ix86_stack_protector_guard_reg = seg; + } + /* Handle -mmemcpy-strategy= and -mmemset-strategy= */ if (opts->x_ix86_tune_memcpy_strategy) { @@ -6678,6 +6732,12 @@ ix86_option_override_internal (bool main_args_p, free (str); } + /* Save the initial options in case the user does function specific + options. */ + if (main_args_p) + target_option_default_node = target_option_current_node + = build_target_option_node (opts); + return true; } @@ -7336,16 +7396,6 @@ ix86_valid_target_attribute_tree (tree args, /* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */ if (enum_opts_set.x_ix86_fpmath) opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; - else if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) - && TARGET_SSE_P (opts->x_ix86_isa_flags)) - { - if (TARGET_80387_P (opts->x_target_flags)) - opts->x_ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE - | FPMATH_387); - else - opts->x_ix86_fpmath = (enum fpmath_unit) FPMATH_SSE; - opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; - } /* Do any overrides, such as arch=xxx, or tune=xxx support. */ bool r = ix86_option_override_internal (false, opts, opts_set); @@ -7440,53 +7490,54 @@ ix86_valid_target_attribute_p (tree fndecl, static bool ix86_can_inline_p (tree caller, tree callee) { - bool ret = false; tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller); tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee); - - /* If callee has no option attributes, then it is ok to inline. */ if (!callee_tree) - ret = true; - - /* If caller has no option attributes, but callee does then it is not ok to - inline. */ - else if (!caller_tree) - ret = false; + callee_tree = target_option_default_node; + if (!caller_tree) + caller_tree = target_option_default_node; + if (callee_tree == caller_tree) + return true; - else - { - struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree); - struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree); + struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree); + bool ret = false; - /* Callee's isa options should be a subset of the caller's, i.e. a SSE4 - function can inline a SSE2 function but a SSE2 function can't inline - a SSE4 function. */ - if (((caller_opts->x_ix86_isa_flags & callee_opts->x_ix86_isa_flags) - != callee_opts->x_ix86_isa_flags) - || ((caller_opts->x_ix86_isa_flags2 & callee_opts->x_ix86_isa_flags2) - != callee_opts->x_ix86_isa_flags2)) - ret = false; + /* Callee's isa options should be a subset of the caller's, i.e. a SSE4 + function can inline a SSE2 function but a SSE2 function can't inline + a SSE4 function. */ + if (((caller_opts->x_ix86_isa_flags & callee_opts->x_ix86_isa_flags) + != callee_opts->x_ix86_isa_flags) + || ((caller_opts->x_ix86_isa_flags2 & callee_opts->x_ix86_isa_flags2) + != callee_opts->x_ix86_isa_flags2)) + ret = false; - /* See if we have the same non-isa options. */ - else if (caller_opts->x_target_flags != callee_opts->x_target_flags) - ret = false; + /* See if we have the same non-isa options. */ + else if (caller_opts->x_target_flags != callee_opts->x_target_flags) + ret = false; - /* See if arch, tune, etc. are the same. */ - else if (caller_opts->arch != callee_opts->arch) - ret = false; + /* See if arch, tune, etc. are the same. */ + else if (caller_opts->arch != callee_opts->arch) + ret = false; - else if (caller_opts->tune != callee_opts->tune) - ret = false; + else if (caller_opts->tune != callee_opts->tune) + ret = false; - else if (caller_opts->x_ix86_fpmath != callee_opts->x_ix86_fpmath) - ret = false; + else if (caller_opts->x_ix86_fpmath != callee_opts->x_ix86_fpmath + /* If the calle doesn't use FP expressions differences in + ix86_fpmath can be ignored. We are called from FEs + for multi-versioning call optimization, so beware of + ipa_fn_summaries not available. */ + && (! ipa_fn_summaries + || ipa_fn_summaries->get + (cgraph_node::get (callee))->fp_expressions)) + ret = false; - else if (caller_opts->branch_cost != callee_opts->branch_cost) - ret = false; + else if (caller_opts->branch_cost != callee_opts->branch_cost) + ret = false; - else - ret = true; - } + else + ret = true; return ret; } @@ -7522,6 +7573,10 @@ ix86_set_func_type (tree fndecl) if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) { + if (ix86_function_naked (fndecl)) + error_at (DECL_SOURCE_LOCATION (fndecl), + "interrupt and naked attributes are not compatible"); + int nargs = 0; for (tree arg = DECL_ARGUMENTS (fndecl); arg; @@ -7929,6 +7984,9 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) rtx a, b; bool bind_global = decl && !targetm.binds_local_p (decl); + if (ix86_function_naked (current_function_decl)) + return false; + /* Sibling call isn't OK if there are no caller-saved registers since all registers must be preserved before return. */ if (cfun->machine->no_caller_saved_registers) @@ -8708,8 +8766,12 @@ ix86_function_type_abi (const_tree fntype) if (abi == SYSV_ABI && lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype))) { - if (TARGET_X32) - error ("X32 does not support ms_abi attribute"); + static int warned; + if (TARGET_X32 && !warned) + { + error ("X32 does not support ms_abi attribute"); + warned = 1; + } abi = MS_ABI; } @@ -12857,13 +12919,12 @@ ix86_compute_frame_layout (void) { unsigned count = xlogue_layout::count_stub_managed_regs (); m->call_ms2sysv_extra_regs = count - xlogue_layout::MIN_REGS; + m->call_ms2sysv_pad_in = 0; } } frame->nregs = ix86_nsaved_regs (); frame->nsseregs = ix86_nsaved_sseregs (); - m->call_ms2sysv_pad_in = 0; - m->call_ms2sysv_pad_out = 0; /* 64-bit MS ABI seem to require stack alignment to be always 16, except for function prologues, leaf functions and when the defult @@ -12885,6 +12946,14 @@ ix86_compute_frame_layout (void) gcc_assert (preferred_alignment >= STACK_BOUNDARY / BITS_PER_UNIT); gcc_assert (preferred_alignment <= stack_alignment_needed); + /* The only ABI saving SSE regs should be 64-bit ms_abi. */ + gcc_assert (TARGET_64BIT || !frame->nsseregs); + if (TARGET_64BIT && m->call_ms2sysv) + { + gcc_assert (stack_alignment_needed >= 16); + gcc_assert (!frame->nsseregs); + } + /* For SEH we have to limit the amount of code movement into the prologue. At present we do this via a BLOCKAGE, at which point there's very little scheduling that can be done, which means that there's very little point @@ -12947,62 +13016,88 @@ ix86_compute_frame_layout (void) if (TARGET_SEH) frame->hard_frame_pointer_offset = offset; - /* When re-aligning the stack frame, but not saving SSE registers, this - is the offset we want adjust the stack pointer to. */ - frame->stack_realign_allocate_offset = offset; + /* Calculate the size of the va-arg area (not including padding, if any). */ + frame->va_arg_size = ix86_varargs_gpr_size + ix86_varargs_fpr_size; - /* The re-aligned stack starts here. Values before this point are not - directly comparable with values below this point. Use sp_valid_at - to determine if the stack pointer is valid for a given offset and - fp_valid_at for the frame pointer. */ if (stack_realign_fp) - offset = ROUND_UP (offset, stack_alignment_needed); - frame->stack_realign_offset = offset; - - if (TARGET_64BIT && m->call_ms2sysv) { - gcc_assert (stack_alignment_needed >= 16); - gcc_assert (!frame->nsseregs); + /* We may need a 16-byte aligned stack for the remainder of the + register save area, but the stack frame for the local function + may require a greater alignment if using AVX/2/512. In order + to avoid wasting space, we first calculate the space needed for + the rest of the register saves, add that to the stack pointer, + and then realign the stack to the boundary of the start of the + frame for the local function. */ + HOST_WIDE_INT space_needed = 0; + HOST_WIDE_INT sse_reg_space_needed = 0; - m->call_ms2sysv_pad_in = !!(offset & UNITS_PER_WORD); + if (TARGET_64BIT) + { + if (m->call_ms2sysv) + { + m->call_ms2sysv_pad_in = 0; + space_needed = xlogue_layout::get_instance ().get_stack_space_used (); + } - /* Select an appropriate layout for incoming stack offset. */ - const struct xlogue_layout &xlogue = xlogue_layout::get_instance (); + else if (frame->nsseregs) + /* The only ABI that has saved SSE registers (Win64) also has a + 16-byte aligned default stack. However, many programs violate + the ABI, and Wine64 forces stack realignment to compensate. */ + space_needed = frame->nsseregs * 16; - if ((offset + xlogue.get_stack_space_used ()) & UNITS_PER_WORD) - m->call_ms2sysv_pad_out = 1; + sse_reg_space_needed = space_needed = ROUND_UP (space_needed, 16); - offset += xlogue.get_stack_space_used (); - gcc_assert (!(offset & 0xf)); - frame->outlined_save_offset = offset; - } + /* 64-bit frame->va_arg_size should always be a multiple of 16, but + rounding to be pedantic. */ + space_needed = ROUND_UP (space_needed + frame->va_arg_size, 16); + } + else + space_needed = frame->va_arg_size; - /* Align and set SSE register save area. */ - else if (frame->nsseregs) - { - /* The only ABI that has saved SSE registers (Win64) also has a - 16-byte aligned default stack. However, many programs violate - the ABI, and Wine64 forces stack realignment to compensate. + /* Record the allocation size required prior to the realignment AND. */ + frame->stack_realign_allocate = space_needed; + + /* The re-aligned stack starts at frame->stack_realign_offset. Values + before this point are not directly comparable with values below + this point. Use sp_valid_at to determine if the stack pointer is + valid for a given offset, fp_valid_at for the frame pointer, or + choose_baseaddr to have a base register chosen for you. - If the incoming stack boundary is at least 16 bytes, or DRAP is - required and the DRAP re-alignment boundary is at least 16 bytes, - then we want the SSE register save area properly aligned. */ - if (ix86_incoming_stack_boundary >= 128 - || (stack_realign_drap && stack_alignment_needed >= 16)) - offset = ROUND_UP (offset, 16); - offset += frame->nsseregs * 16; - frame->stack_realign_allocate_offset = offset; + Note that the result of (frame->stack_realign_offset + & (stack_alignment_needed - 1)) may not equal zero. */ + offset = ROUND_UP (offset + space_needed, stack_alignment_needed); + frame->stack_realign_offset = offset - space_needed; + frame->sse_reg_save_offset = frame->stack_realign_offset + + sse_reg_space_needed; } + else + { + frame->stack_realign_offset = offset; - frame->sse_reg_save_offset = offset; + if (TARGET_64BIT && m->call_ms2sysv) + { + m->call_ms2sysv_pad_in = !!(offset & UNITS_PER_WORD); + offset += xlogue_layout::get_instance ().get_stack_space_used (); + } - /* Va-arg area */ - frame->va_arg_size = ix86_varargs_gpr_size + ix86_varargs_fpr_size; - offset += frame->va_arg_size; + /* Align and set SSE register save area. */ + else if (frame->nsseregs) + { + /* If the incoming stack boundary is at least 16 bytes, or DRAP is + required and the DRAP re-alignment boundary is at least 16 bytes, + then we want the SSE register save area properly aligned. */ + if (ix86_incoming_stack_boundary >= 128 + || (stack_realign_drap && stack_alignment_needed >= 16)) + offset = ROUND_UP (offset, 16); + offset += frame->nsseregs * 16; + } + frame->sse_reg_save_offset = offset; + offset += frame->va_arg_size; + } /* Align start of frame for local function. */ - if (stack_realign_fp - || offset != frame->sse_reg_save_offset + if (m->call_ms2sysv + || frame->va_arg_size != 0 || size != 0 || !crtl->is_leaf || cfun->calls_alloca @@ -13110,26 +13205,36 @@ choose_baseaddr_len (unsigned int regno, HOST_WIDE_INT offset) return len; } -/* Determine if the stack pointer is valid for accessing the cfa_offset. - The register is saved at CFA - CFA_OFFSET. */ +/* Determine if the stack pointer is valid for accessing the CFA_OFFSET in + the frame save area. The register is saved at CFA - CFA_OFFSET. */ -static inline bool +static bool sp_valid_at (HOST_WIDE_INT cfa_offset) { const struct machine_frame_state &fs = cfun->machine->fs; - return fs.sp_valid && !(fs.sp_realigned - && cfa_offset <= fs.sp_realigned_offset); + if (fs.sp_realigned && cfa_offset <= fs.sp_realigned_offset) + { + /* Validate that the cfa_offset isn't in a "no-man's land". */ + gcc_assert (cfa_offset <= fs.sp_realigned_fp_last); + return false; + } + return fs.sp_valid; } -/* Determine if the frame pointer is valid for accessing the cfa_offset. - The register is saved at CFA - CFA_OFFSET. */ +/* Determine if the frame pointer is valid for accessing the CFA_OFFSET in + the frame save area. The register is saved at CFA - CFA_OFFSET. */ static inline bool fp_valid_at (HOST_WIDE_INT cfa_offset) { const struct machine_frame_state &fs = cfun->machine->fs; - return fs.fp_valid && !(fs.sp_valid && fs.sp_realigned - && cfa_offset > fs.sp_realigned_offset); + if (fs.sp_realigned && cfa_offset > fs.sp_realigned_fp_last) + { + /* Validate that the cfa_offset isn't in a "no-man's land". */ + gcc_assert (cfa_offset >= fs.sp_realigned_offset); + return false; + } + return fs.fp_valid; } /* Choose a base register based upon alignment requested, speed and/or @@ -13240,10 +13345,13 @@ choose_basereg (HOST_WIDE_INT cfa_offset, rtx &base_reg, } /* Return an RTX that points to CFA_OFFSET within the stack frame and - the alignment of address. If align is non-null, it should point to + the alignment of address. If ALIGN is non-null, it should point to an alignment value (in bits) that is preferred or zero and will - recieve the alignment of the base register that was selected. The - valid base registers are taken from CFUN->MACHINE->FS. */ + recieve the alignment of the base register that was selected, + irrespective of rather or not CFA_OFFSET is a multiple of that + alignment value. + + The valid base registers are taken from CFUN->MACHINE->FS. */ static rtx choose_baseaddr (HOST_WIDE_INT cfa_offset, unsigned int *align) @@ -14119,10 +14227,11 @@ output_probe_stack_range (rtx reg, rtx end) return ""; } -/* Finalize stack_realign_needed flag, which will guide prologue/epilogue - to be generated in correct form. */ +/* Finalize stack_realign_needed and frame_pointer_needed flags, which + will guide prologue/epilogue to be generated in correct form. */ + static void -ix86_finalize_stack_realign_flags (void) +ix86_finalize_stack_frame_flags (void) { /* Check if stack realign is really needed after reload, and stores result in cfun */ @@ -14145,13 +14254,13 @@ ix86_finalize_stack_realign_flags (void) } /* If the only reason for frame_pointer_needed is that we conservatively - assumed stack realignment might be needed, but in the end nothing that - needed the stack alignment had been spilled, clear frame_pointer_needed - and say we don't need stack realignment. */ - if (stack_realign + assumed stack realignment might be needed or -fno-omit-frame-pointer + is used, but in the end nothing that needed the stack alignment had + been spilled nor stack access, clear frame_pointer_needed and say we + don't need stack realignment. */ + if ((stack_realign || !flag_omit_frame_pointer) && frame_pointer_needed && crtl->is_leaf - && flag_omit_frame_pointer && crtl->sp_is_unchanging && !ix86_current_function_calls_tls_descriptor && !crtl->accesses_prior_frames @@ -14220,6 +14329,42 @@ ix86_finalize_stack_realign_flags (void) df_scan_blocks (); df_compute_regs_ever_live (true); df_analyze (); + + if (flag_var_tracking) + { + /* Since frame pointer is no longer available, replace it with + stack pointer - UNITS_PER_WORD in debug insns. */ + df_ref ref, next; + for (ref = DF_REG_USE_CHAIN (HARD_FRAME_POINTER_REGNUM); + ref; ref = next) + { + rtx_insn *insn = DF_REF_INSN (ref); + /* Make sure the next ref is for a different instruction, + so that we're not affected by the rescan. */ + next = DF_REF_NEXT_REG (ref); + while (next && DF_REF_INSN (next) == insn) + next = DF_REF_NEXT_REG (next); + + if (DEBUG_INSN_P (insn)) + { + bool changed = false; + for (; ref != next; ref = DF_REF_NEXT_REG (ref)) + { + rtx *loc = DF_REF_LOC (ref); + if (*loc == hard_frame_pointer_rtx) + { + *loc = plus_constant (Pmode, + stack_pointer_rtx, + -UNITS_PER_WORD); + changed = true; + } + } + if (changed) + df_insn_rescan (insn); + } + } + } + recompute_frame_layout_p = true; } @@ -14289,35 +14434,35 @@ ix86_emit_outlined_ms2sysv_save (const struct ix86_frame &frame) rtx sym, addr; rtx rax = gen_rtx_REG (word_mode, AX_REG); const struct xlogue_layout &xlogue = xlogue_layout::get_instance (); - HOST_WIDE_INT rax_offset = xlogue.get_stub_ptr_offset () + m->fs.sp_offset; - HOST_WIDE_INT stack_alloc_size = frame.stack_pointer_offset - m->fs.sp_offset; - HOST_WIDE_INT stack_align_off_in = xlogue.get_stack_align_off_in (); + HOST_WIDE_INT allocate = frame.stack_pointer_offset - m->fs.sp_offset; - /* Verify that the incoming stack 16-byte alignment offset matches the - layout we're using. */ - gcc_assert (stack_align_off_in == (m->fs.sp_offset & UNITS_PER_WORD)); + /* AL should only be live with sysv_abi. */ + gcc_assert (!ix86_eax_live_at_start_p ()); + + /* Setup RAX as the stub's base pointer. We use stack_realign_offset rather + we've actually realigned the stack or not. */ + align = GET_MODE_ALIGNMENT (V4SFmode); + addr = choose_baseaddr (frame.stack_realign_offset + + xlogue.get_stub_ptr_offset (), &align); + gcc_assert (align >= GET_MODE_ALIGNMENT (V4SFmode)); + emit_insn (gen_rtx_SET (rax, addr)); + + /* Allocate stack if not already done. */ + if (allocate > 0) + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-allocate), -1, false); /* Get the stub symbol. */ sym = xlogue.get_stub_rtx (frame_pointer_needed ? XLOGUE_STUB_SAVE_HFP : XLOGUE_STUB_SAVE); RTVEC_ELT (v, vi++) = gen_rtx_USE (VOIDmode, sym); - /* Setup RAX as the stub's base pointer. */ - align = GET_MODE_ALIGNMENT (V4SFmode); - addr = choose_baseaddr (rax_offset, &align); - gcc_assert (align >= GET_MODE_ALIGNMENT (V4SFmode)); - insn = emit_insn (gen_rtx_SET (rax, addr)); - - gcc_assert (stack_alloc_size >= xlogue.get_stack_space_used ()); - pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-stack_alloc_size), -1, - m->fs.cfa_reg == stack_pointer_rtx); for (i = 0; i < ncregs; ++i) { const xlogue_layout::reginfo &r = xlogue.get_reginfo (i); rtx reg = gen_rtx_REG ((SSE_REGNO_P (r.regno) ? V4SFmode : word_mode), r.regno); - RTVEC_ELT (v, vi++) = gen_frame_store (reg, rax, -r.offset);; + RTVEC_ELT (v, vi++) = gen_frame_store (reg, rax, -r.offset); } gcc_assert (vi == (unsigned)GET_NUM_ELEM (v)); @@ -14342,7 +14487,7 @@ ix86_expand_prologue (void) if (ix86_function_naked (current_function_decl)) return; - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); /* DRAP should not coexist with stack_realign_fp */ gcc_assert (!(crtl->drap_reg && stack_realign_fp)); @@ -14571,12 +14716,16 @@ ix86_expand_prologue (void) int align_bytes = crtl->stack_alignment_needed / BITS_PER_UNIT; gcc_assert (align_bytes > MIN_STACK_BOUNDARY / BITS_PER_UNIT); + /* Record last valid frame pointer offset. */ + m->fs.sp_realigned_fp_last = frame.reg_save_offset; + /* The computation of the size of the re-aligned stack frame means that we must allocate the size of the register save area before performing the actual alignment. Otherwise we cannot guarantee that there's enough storage above the realignment point. */ - allocate = frame.stack_realign_allocate_offset - m->fs.sp_offset; - if (allocate && !m->call_ms2sysv) + allocate = frame.reg_save_offset - m->fs.sp_offset + + frame.stack_realign_allocate; + if (allocate) pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-allocate), -1, false); @@ -14584,14 +14733,18 @@ ix86_expand_prologue (void) insn = emit_insn (ix86_gen_andsp (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-align_bytes))); - /* For the purposes of register save area addressing, the stack - pointer can no longer be used to access anything in the frame - below m->fs.sp_realigned_offset and the frame pointer cannot be - used for anything at or above. */ m->fs.sp_offset = ROUND_UP (m->fs.sp_offset, align_bytes); - m->fs.sp_realigned = true; - m->fs.sp_realigned_offset = m->fs.sp_offset - frame.nsseregs * 16; + m->fs.sp_realigned_offset = m->fs.sp_offset + - frame.stack_realign_allocate; + /* The stack pointer may no longer be equal to CFA - m->fs.sp_offset. + Beyond this point, stack access should be done via choose_baseaddr or + by using sp_valid_at and fp_valid_at to determine the correct base + register. Henceforth, any CFA offset should be thought of as logical + and not physical. */ + gcc_assert (m->fs.sp_realigned_offset >= m->fs.sp_realigned_fp_last); gcc_assert (m->fs.sp_realigned_offset == frame.stack_realign_offset); + m->fs.sp_realigned = true; + /* SEH unwind emit doesn't currently support REG_CFA_EXPRESSION, which is needed to describe where a register is saved using a realigned stack pointer, so we need to invalidate the stack pointer for that @@ -14653,7 +14806,7 @@ ix86_expand_prologue (void) so probe if the size is non-negative to preserve the protection area. */ if (allocate >= 0 && flag_stack_check == STATIC_BUILTIN_STACK_CHECK) { - /* We expect the registers to be saved when probes are used. */ + /* We expect the GP registers to be saved when probes are used. */ gcc_assert (int_registers_saved); if (STACK_CHECK_MOVING_SP) @@ -15202,11 +15355,11 @@ ix86_expand_epilogue (int style) if (ix86_function_naked (current_function_decl)) { /* The program should not reach this point. */ - emit_insn (gen_trap ()); + emit_insn (gen_ud2 ()); return; } - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); frame = m->frame; m->fs.sp_realigned = stack_realign_fp; @@ -15288,10 +15441,10 @@ ix86_expand_epilogue (int style) if (restore_regs_via_mov || frame.nsseregs) { /* Ensure that the entire register save area is addressable via - the stack pointer, if we will restore via sp. */ + the stack pointer, if we will restore SSE regs via sp. */ if (TARGET_64BIT && m->fs.sp_offset > 0x7fffffff - && !(fp_valid_at (frame.stack_realign_offset) || m->fs.drap_valid) + && sp_valid_at (frame.stack_realign_offset) && (frame.nsseregs + frame.nregs) != 0) { pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx, @@ -15580,7 +15733,7 @@ ix86_expand_epilogue (int style) /* Reset from the function's potential modifications. */ static void -ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, HOST_WIDE_INT) +ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED) { if (pic_offset_table_rtx && !ix86_use_pseudo_pic_reg ()) @@ -15724,6 +15877,30 @@ static GTY(()) rtx split_stack_fn; static GTY(()) rtx split_stack_fn_large; +/* Return location of the stack guard value in the TLS block. */ + +rtx +ix86_split_stack_guard (void) +{ + int offset; + addr_space_t as = DEFAULT_TLS_SEG_REG; + rtx r; + + gcc_assert (flag_split_stack); + +#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET + offset = TARGET_THREAD_SPLIT_STACK_OFFSET; +#else + gcc_unreachable (); +#endif + + r = GEN_INT (offset); + r = gen_const_mem (Pmode, r); + set_mem_addr_space (r, as); + + return r; +} + /* Handle -fsplit-stack. These are the first instructions in the function, even before the regular prologue. */ @@ -15741,7 +15918,7 @@ ix86_expand_split_stack_prologue (void) gcc_assert (flag_split_stack && reload_completed); - ix86_finalize_stack_realign_flags (); + ix86_finalize_stack_frame_flags (); frame = cfun->machine->frame; allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET; @@ -15755,10 +15932,8 @@ ix86_expand_split_stack_prologue (void) us SPLIT_STACK_AVAILABLE bytes, so if we need less than that we can compare directly. Otherwise we need to do an addition. */ - limit = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), - UNSPEC_STACK_CHECK); - limit = gen_rtx_CONST (Pmode, limit); - limit = gen_rtx_MEM (Pmode, limit); + limit = ix86_split_stack_guard (); + if (allocate < SPLIT_STACK_AVAILABLE) current = stack_pointer_rtx; else @@ -16831,10 +17006,6 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) case UNSPEC_DTPOFF: break; - case UNSPEC_STACK_CHECK: - gcc_assert (flag_split_stack); - break; - default: /* Invalid address unspec. */ return false; @@ -17924,17 +18095,10 @@ output_pic_addr_const (FILE *file, rtx x, int code) putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file); break; - case UNSPEC: - if (XINT (x, 1) == UNSPEC_STACK_CHECK) - { - bool f = i386_asm_output_addr_const_extra (file, x); - gcc_assert (f); - break; - } - - gcc_assert (XVECLEN (x, 0) == 1); - output_pic_addr_const (file, XVECEXP (x, 0, 0), code); - switch (XINT (x, 1)) + case UNSPEC: + gcc_assert (XVECLEN (x, 0) == 1); + output_pic_addr_const (file, XVECEXP (x, 0, 0), code); + switch (XINT (x, 1)) { case UNSPEC_GOT: fputs ("@GOT", file); @@ -18627,7 +18791,6 @@ print_reg (rtx x, int code, FILE *file) + -- print a branch hint as 'cs' or 'ds' prefix ; -- print a semicolon (after prefixes due to bug in older gas). ~ -- print "i" if TARGET_AVX2, "f" otherwise. - @ -- print a segment register of thread base pointer load ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode ! -- print MPX prefix for jxx/call/ret instructions if required. */ @@ -19171,19 +19334,6 @@ ix86_print_operand (FILE *file, rtx x, int code) #endif return; - case '@': - if (ASSEMBLER_DIALECT == ASM_ATT) - putc ('%', file); - - /* The kernel uses a different segment register for performance - reasons; a system call would not have to trash the userspace - segment register, which would be expensive. */ - if (TARGET_64BIT && ix86_cmodel != CM_KERNEL) - fputs ("fs", file); - else - fputs ("gs", file); - return; - case '~': putc (TARGET_AVX2 ? 'i' : 'f', file); return; @@ -19342,8 +19492,8 @@ ix86_print_operand (FILE *file, rtx x, int code) static bool ix86_print_operand_punct_valid_p (unsigned char code) { - return (code == '@' || code == '*' || code == '+' || code == '&' - || code == ';' || code == '~' || code == '^' || code == '!'); + return (code == '*' || code == '+' || code == '&' || code == ';' + || code == '~' || code == '^' || code == '!'); } /* Print a memory operand whose address is ADDR. */ @@ -19442,7 +19592,7 @@ ix86_print_operand_address_as (FILE *file, rtx addr, /* Displacement only requires special attention. */ if (CONST_INT_P (disp)) { - if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == ADDR_SPACE_GENERIC) + if (ASSEMBLER_DIALECT == ASM_INTEL && ADDR_SPACE_GENERIC_P (as)) fputs ("ds:", file); fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp)); } @@ -19644,22 +19794,6 @@ i386_asm_output_addr_const_extra (FILE *file, rtx x) break; #endif - case UNSPEC_STACK_CHECK: - { - int offset; - - gcc_assert (flag_split_stack); - -#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET - offset = TARGET_THREAD_SPLIT_STACK_OFFSET; -#else - gcc_unreachable (); -#endif - - fprintf (file, "%s:%d", TARGET_64BIT ? "%fs" : "%gs", offset); - } - break; - default: return false; } @@ -33420,13 +33554,18 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) break; case PROCESSOR_NEHALEM: if (new_target->x_ix86_isa_flags & OPTION_MASK_ISA_AES) - arg_str = "westmere"; + { + arg_str = "westmere"; + priority = P_AES; + } else - /* We translate "arch=corei7" and "arch=nehalem" to - "corei7" so that it will be mapped to M_INTEL_COREI7 - as cpu type to cover all M_INTEL_COREI7_XXXs. */ - arg_str = "corei7"; - priority = P_PROC_SSE4_2; + { + /* We translate "arch=corei7" and "arch=nehalem" to + "corei7" so that it will be mapped to M_INTEL_COREI7 + as cpu type to cover all M_INTEL_COREI7_XXXs. */ + arg_str = "corei7"; + priority = P_PROC_SSE4_2; + } break; case PROCESSOR_SANDYBRIDGE: if (new_target->x_ix86_isa_flags & OPTION_MASK_ISA_F16C) @@ -33866,30 +34005,30 @@ ix86_get_function_versions_dispatcher (void *decl) } /* Make the resolver function decl to dispatch the versions of - a multi-versioned function, DEFAULT_DECL. Create an + a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is + ifunc alias that will point to the created resolver. Create an empty basic block in the resolver and store the pointer in EMPTY_BB. Return the decl of the resolver function. */ static tree make_resolver_func (const tree default_decl, - const tree dispatch_decl, + const tree ifunc_alias_decl, basic_block *empty_bb) { char *resolver_name; tree decl, type, decl_name, t; - bool is_uniq = false; /* IFUNC's have to be globally visible. So, if the default_decl is not, then the name of the IFUNC should be made unique. */ if (TREE_PUBLIC (default_decl) == 0) - is_uniq = true; + { + char *ifunc_name = make_unique_name (default_decl, "ifunc", true); + symtab->change_decl_assembler_name (ifunc_alias_decl, + get_identifier (ifunc_name)); + XDELETEVEC (ifunc_name); + } - /* Append the filename to the resolver function if the versions are - not externally visible. This is because the resolver function has - to be externally visible for the loader to find it. So, appending - the filename will prevent conflicts with a resolver function from - another module which is based on the same version name. */ - resolver_name = make_unique_name (default_decl, "resolver", is_uniq); + resolver_name = make_unique_name (default_decl, "resolver", false); /* The resolver function should return a (void *). */ type = build_function_type_list (ptr_type_node, NULL_TREE); @@ -33901,14 +34040,13 @@ make_resolver_func (const tree default_decl, DECL_NAME (decl) = decl_name; TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 0; - /* IFUNC resolvers have to be externally visible. */ - TREE_PUBLIC (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_PUBLIC (decl) = 0; DECL_UNINLINABLE (decl) = 1; /* Resolver is not external, body is generated. */ DECL_EXTERNAL (decl) = 0; - DECL_EXTERNAL (dispatch_decl) = 0; + DECL_EXTERNAL (ifunc_alias_decl) = 0; DECL_CONTEXT (decl) = NULL_TREE; DECL_INITIAL (decl) = make_node (BLOCK); @@ -33939,14 +34077,14 @@ make_resolver_func (const tree default_decl, pop_cfun (); - gcc_assert (dispatch_decl != NULL); - /* Mark dispatch_decl as "ifunc" with resolver as resolver_name. */ - DECL_ATTRIBUTES (dispatch_decl) - = make_attribute ("ifunc", resolver_name, DECL_ATTRIBUTES (dispatch_decl)); + gcc_assert (ifunc_alias_decl != NULL); + /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name. */ + DECL_ATTRIBUTES (ifunc_alias_decl) + = make_attribute ("ifunc", resolver_name, + DECL_ATTRIBUTES (ifunc_alias_decl)); /* Create the alias for dispatch to resolver here. */ - /*cgraph_create_function_alias (dispatch_decl, decl);*/ - cgraph_node::create_same_body_alias (dispatch_decl, decl); + cgraph_node::create_same_body_alias (ifunc_alias_decl, decl); XDELETEVEC (resolver_name); return decl; } @@ -39827,7 +39965,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_LFLOOR: CASE_CFN_LLFLOOR: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == SImode && in_mode == DFmode) @@ -39854,7 +39992,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_LCEIL: CASE_CFN_LLCEIL: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == SImode && in_mode == DFmode) @@ -39904,7 +40042,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_LROUND: CASE_CFN_LLROUND: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == SImode && in_mode == DFmode) @@ -39929,7 +40067,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_FLOOR: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == DFmode && in_mode == DFmode) @@ -39954,7 +40092,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_CEIL: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == DFmode && in_mode == DFmode) @@ -39979,7 +40117,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_TRUNC: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == DFmode && in_mode == DFmode) @@ -40004,7 +40142,7 @@ ix86_builtin_vectorized_function (unsigned int fn, tree type_out, CASE_CFN_RINT: /* The round insn does not trap on denormals. */ - if (flag_trapping_math || !TARGET_ROUND) + if (flag_trapping_math || !TARGET_SSE4_1) break; if (out_mode == DFmode && in_mode == DFmode) @@ -44318,6 +44456,34 @@ ix86_expand_vector_init (bool mmx_ok, rtx target, rtx vals) int i; rtx x; + /* Handle first initialization from vector elts. */ + if (n_elts != XVECLEN (vals, 0)) + { + rtx subtarget = target; + x = XVECEXP (vals, 0, 0); + gcc_assert (GET_MODE_INNER (GET_MODE (x)) == inner_mode); + if (GET_MODE_NUNITS (GET_MODE (x)) * 2 == n_elts) + { + rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) }; + if (inner_mode == QImode || inner_mode == HImode) + { + mode = mode_for_vector (SImode, + n_elts * GET_MODE_SIZE (inner_mode) / 4); + inner_mode + = mode_for_vector (SImode, + n_elts * GET_MODE_SIZE (inner_mode) / 8); + ops[0] = gen_lowpart (inner_mode, ops[0]); + ops[1] = gen_lowpart (inner_mode, ops[1]); + subtarget = gen_reg_rtx (mode); + } + ix86_expand_vector_init_concat (mode, subtarget, ops, 2); + if (subtarget != target) + emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget)); + return; + } + gcc_unreachable (); + } + for (i = 0; i < n_elts; ++i) { x = XVECEXP (vals, 0, i); @@ -45779,17 +45945,60 @@ ix86_mangle_type (const_tree type) } } -#ifdef TARGET_THREAD_SSP_OFFSET -/* If using TLS guards, don't waste time creating and expanding - __stack_chk_guard decl and MEM as we are going to ignore it. */ +static GTY(()) tree ix86_tls_stack_chk_guard_decl; + static tree ix86_stack_protect_guard (void) { if (TARGET_SSP_TLS_GUARD) - return NULL_TREE; + { + tree type_node = lang_hooks.types.type_for_mode (ptr_mode, 1); + int qual = ENCODE_QUAL_ADDR_SPACE (ix86_stack_protector_guard_reg); + tree type = build_qualified_type (type_node, qual); + tree t; + + if (global_options_set.x_ix86_stack_protector_guard_symbol_str) + { + t = ix86_tls_stack_chk_guard_decl; + + if (t == NULL) + { + rtx x; + + t = build_decl + (UNKNOWN_LOCATION, VAR_DECL, + get_identifier (ix86_stack_protector_guard_symbol_str), + type); + TREE_STATIC (t) = 1; + TREE_PUBLIC (t) = 1; + DECL_EXTERNAL (t) = 1; + TREE_USED (t) = 1; + TREE_THIS_VOLATILE (t) = 1; + DECL_ARTIFICIAL (t) = 1; + DECL_IGNORED_P (t) = 1; + + /* Do not share RTL as the declaration is visible outside of + current function. */ + x = DECL_RTL (t); + RTX_FLAG (x, used) = 1; + + ix86_tls_stack_chk_guard_decl = t; + } + } + else + { + tree asptrtype = build_pointer_type (type); + + t = build_int_cst (asptrtype, ix86_stack_protector_guard_offset); + t = build2 (MEM_REF, asptrtype, t, + build_int_cst (asptrtype, 0)); + } + + return t; + } + return default_stack_protect_guard (); } -#endif /* For 32-bit code we can save PIC register setup by using __stack_chk_fail_local hidden function instead of calling @@ -52128,7 +52337,7 @@ ix86_optab_supported_p (int op, machine_mode mode1, machine_mode, if (SSE_FLOAT_MODE_P (mode1) && TARGET_SSE_MATH && !flag_trapping_math - && !TARGET_ROUND) + && !TARGET_SSE4_1) return opt_type == OPTIMIZE_FOR_SPEED; return true; @@ -52138,7 +52347,7 @@ ix86_optab_supported_p (int op, machine_mode mode1, machine_mode, if (SSE_FLOAT_MODE_P (mode1) && TARGET_SSE_MATH && !flag_trapping_math - && TARGET_ROUND) + && TARGET_SSE4_1) return true; return opt_type == OPTIMIZE_FOR_SPEED; @@ -52797,10 +53006,8 @@ ix86_run_selftests (void) #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE ix86_mangle_type -#ifdef TARGET_THREAD_SSP_OFFSET #undef TARGET_STACK_PROTECT_GUARD #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard -#endif #if !TARGET_MACHO #undef TARGET_STACK_PROTECT_FAIL diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index bdea37b73136e..dad6499ca1d14 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -97,7 +97,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_XOP_P(x) TARGET_ISA_XOP_P(x) #define TARGET_LWP TARGET_ISA_LWP #define TARGET_LWP_P(x) TARGET_ISA_LWP_P(x) -#define TARGET_ROUND TARGET_ISA_ROUND #define TARGET_ABM TARGET_ISA_ABM #define TARGET_ABM_P(x) TARGET_ISA_ABM_P(x) #define TARGET_SGX TARGET_ISA_SGX @@ -176,10 +175,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_16BIT TARGET_CODE16 #define TARGET_16BIT_P(x) TARGET_CODE16_P(x) -/* SSE4.1 defines round instructions */ -#define OPTION_MASK_ISA_ROUND OPTION_MASK_ISA_SSE4_1 -#define TARGET_ISA_ROUND ((ix86_isa_flags & OPTION_MASK_ISA_ROUND) != 0) - #include "config/vxworks-dummy.h" #include "config/i386/i386-opts.h" @@ -2484,8 +2479,7 @@ enum avx_u128_state <- end of stub-saved/restored regs [padding1] ] - <- outlined_save_offset - <- sse_regs_save_offset + <- sse_reg_save_offset [padding2] | <- FRAME_POINTER [va_arg registers] | @@ -2509,9 +2503,8 @@ struct GTY(()) ix86_frame HOST_WIDE_INT stack_pointer_offset; HOST_WIDE_INT hfp_save_offset; HOST_WIDE_INT reg_save_offset; - HOST_WIDE_INT stack_realign_allocate_offset; + HOST_WIDE_INT stack_realign_allocate; HOST_WIDE_INT stack_realign_offset; - HOST_WIDE_INT outlined_save_offset; HOST_WIDE_INT sse_reg_save_offset; /* When save_regs_using_mov is set, emit prologue using @@ -2519,7 +2512,9 @@ struct GTY(()) ix86_frame bool save_regs_using_mov; }; -/* Machine specific frame tracking during prologue/epilogue generation. */ +/* Machine specific frame tracking during prologue/epilogue generation. All + values are positive, but since the x86 stack grows downward, are subtratced + from the CFA to produce a valid address. */ struct GTY(()) machine_frame_state { @@ -2557,13 +2552,19 @@ struct GTY(()) machine_frame_state /* Indicates whether the stack pointer has been re-aligned. When set, SP/FP continue to be relative to the CFA, but the stack pointer - should only be used for offsets >= sp_realigned_offset, while - the frame pointer should be used for offsets < sp_realigned_offset. + should only be used for offsets > sp_realigned_offset, while + the frame pointer should be used for offsets <= sp_realigned_fp_last. The flags realigned and sp_realigned are mutually exclusive. */ BOOL_BITFIELD sp_realigned : 1; - /* If sp_realigned is set, this is the offset from the CFA that the - stack pointer was realigned to. */ + /* If sp_realigned is set, this is the last valid offset from the CFA + that can be used for access with the frame pointer. */ + HOST_WIDE_INT sp_realigned_fp_last; + + /* If sp_realigned is set, this is the offset from the CFA that the stack + pointer was realigned, and may or may not be equal to sp_realigned_fp_last. + Access via the stack pointer is only valid for offsets that are greater than + this value. */ HOST_WIDE_INT sp_realigned_offset; }; @@ -2647,17 +2648,13 @@ struct GTY(()) machine_function { BOOL_BITFIELD arg_reg_available : 1; /* If true, we're out-of-lining reg save/restore for regs clobbered - by ms_abi functions calling a sysv function. */ + by 64-bit ms_abi functions calling a sysv_abi function. */ BOOL_BITFIELD call_ms2sysv : 1; /* If true, the incoming 16-byte aligned stack has an offset (of 8) and - needs padding. */ + needs padding prior to out-of-line stub save/restore area. */ BOOL_BITFIELD call_ms2sysv_pad_in : 1; - /* If true, the size of the stub save area plus inline int reg saves will - result in an 8 byte offset, so needs padding. */ - BOOL_BITFIELD call_ms2sysv_pad_out : 1; - /* This is the number of extra registers saved by stub (valid range is 0-6). Each additional register is only saved/restored by the stubs if all successive ones are. (Will always be zero when using a hard diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 5eff4e46fff30..7465848252d6b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -61,7 +61,6 @@ ;; + -- print a branch hint as 'cs' or 'ds' prefix ;; ; -- print a semicolon (after prefixes due to bug in older gas). ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise. -;; @ -- print a segment register of thread base pointer load ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode ;; ! -- print MPX prefix for jxx/call/ret instructions if required. @@ -87,7 +86,6 @@ UNSPEC_SET_RIP UNSPEC_SET_GOT_OFFSET UNSPEC_MEMORY_BLOCKAGE - UNSPEC_STACK_CHECK UNSPEC_PROBE_STACK ;; TLS support @@ -166,8 +164,6 @@ ;; SSP patterns UNSPEC_SP_SET UNSPEC_SP_TEST - UNSPEC_SP_TLS_SET - UNSPEC_SP_TLS_TEST ;; For ROUND support UNSPEC_ROUND @@ -201,6 +197,7 @@ ]) (define_c_enum "unspecv" [ + UNSPECV_UD2 UNSPECV_BLOCKAGE UNSPECV_STACK_PROBE UNSPECV_PROBE_STACK_RANGE @@ -1084,6 +1081,9 @@ ;; Immediate operand constraint for shifts. (define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")]) +;; Print register name in the specified mode. +(define_mode_attr k [(QI "b") (HI "w") (SI "k") (DI "q")]) + ;; General operand predicate for integer modes. (define_mode_attr general_operand [(QI "general_operand") @@ -8270,6 +8270,28 @@ (const_string "*"))) (set_attr "mode" "SI,DI,DI,SI")]) +(define_insn_and_split "*anddi_1_btr" + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (and:DI + (match_operand:DI 1 "nonimmediate_operand" "%0") + (match_operand:DI 2 "const_int_operand" "n"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_USE_BT + && ix86_binary_operator_ok (AND, DImode, operands) + && IN_RANGE (exact_log2 (~INTVAL (operands[2])), 31, 63)" + "#" + "&& reload_completed" + [(parallel [(set (zero_extract:DI (match_dup 0) + (const_int 1) + (match_dup 3)) + (const_int 0)) + (clobber (reg:CC FLAGS_REG))])] + "operands[3] = GEN_INT (exact_log2 (~INTVAL (operands[2])));" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "znver1_decode" "double") + (set_attr "mode" "DI")]) + ;; Turn *anddi_1 into *andsi_1_zext if possible. (define_split [(set (match_operand:DI 0 "register_operand") @@ -8794,6 +8816,52 @@ [(set_attr "type" "alu") (set_attr "mode" "")]) +(define_insn_and_split "*iordi_1_bts" + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (ior:DI + (match_operand:DI 1 "nonimmediate_operand" "%0") + (match_operand:DI 2 "const_int_operand" "n"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_USE_BT + && ix86_binary_operator_ok (IOR, DImode, operands) + && IN_RANGE (exact_log2 (INTVAL (operands[2])), 31, 63)" + "#" + "&& reload_completed" + [(parallel [(set (zero_extract:DI (match_dup 0) + (const_int 1) + (match_dup 3)) + (const_int 1)) + (clobber (reg:CC FLAGS_REG))])] + "operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2])));" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "znver1_decode" "double") + (set_attr "mode" "DI")]) + +(define_insn_and_split "*xordi_1_btc" + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (xor:DI + (match_operand:DI 1 "nonimmediate_operand" "%0") + (match_operand:DI 2 "const_int_operand" "n"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_USE_BT + && ix86_binary_operator_ok (XOR, DImode, operands) + && IN_RANGE (exact_log2 (INTVAL (operands[2])), 31, 63)" + "#" + "&& reload_completed" + [(parallel [(set (zero_extract:DI (match_dup 0) + (const_int 1) + (match_dup 3)) + (not:DI (zero_extract:DI (match_dup 0) + (const_int 1) + (match_dup 3)))) + (clobber (reg:CC FLAGS_REG))])] + "operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2])));" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "znver1_decode" "double") + (set_attr "mode" "DI")]) + ;; See comment for addsi_1_zext why we do use nonimmediate_operand (define_insn "*si_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") @@ -10933,21 +11001,104 @@ ;; Bit set / bit test instructions -;; %%% bts, btr, btc, bt. -;; In general these instructions are *slow* when applied to memory, -;; since they enforce atomic operation. When applied to registers, -;; it depends on the cpu implementation. They're never faster than -;; the corresponding and/ior/xor operations, so with 32-bit there's -;; no point. But in 64-bit, we can't hold the relevant immediates -;; within the instruction itself, so operating on bits in the high -;; 32-bits of a register becomes easier. +;; %%% bts, btr, btc + +;; These instructions are *slow* when applied to memory. + +(define_code_attr btsc [(ior "bts") (xor "btc")]) + +(define_insn "*" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (any_or:SWI48 + (ashift:SWI48 (const_int 1) + (match_operand:QI 2 "register_operand" "r")) + (match_operand:SWI48 1 "register_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_USE_BT" + "{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "znver1_decode" "double") + (set_attr "mode" "")]) + +;; Avoid useless masking of count operand. +(define_insn_and_split "*_mask" + [(set (match_operand:SWI48 0 "register_operand") + (any_or:SWI48 + (ashift:SWI48 + (const_int 1) + (subreg:QI + (and:SI + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")) 0)) + (match_operand:SWI48 3 "register_operand"))) + (clobber (reg:CC FLAGS_REG))] + "(INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode)-1)) + == GET_MODE_BITSIZE (mode)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (any_or:SWI48 + (ashift:SWI48 (const_int 1) + (match_dup 1)) + (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] + "operands[1] = gen_lowpart (QImode, operands[1]);") + +(define_insn "*btr" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (and:SWI48 + (rotate:SWI48 (const_int -2) + (match_operand:QI 2 "register_operand" "r")) + (match_operand:SWI48 1 "register_operand" "0"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_USE_BT" + "btr{}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu1") + (set_attr "prefix_0f" "1") + (set_attr "znver1_decode" "double") + (set_attr "mode" "")]) + +;; Avoid useless masking of count operand. +(define_insn_and_split "*btr_mask" + [(set (match_operand:SWI48 0 "register_operand") + (and:SWI48 + (rotate:SWI48 + (const_int -2) + (subreg:QI + (and:SI + (match_operand:SI 1 "register_operand") + (match_operand:SI 2 "const_int_operand")) 0)) + (match_operand:SWI48 3 "register_operand"))) + (clobber (reg:CC FLAGS_REG))] + "(INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode)-1)) + == GET_MODE_BITSIZE (mode)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (and:SWI48 + (rotate:SWI48 (const_int -2) + (match_dup 1)) + (match_dup 3))) + (clobber (reg:CC FLAGS_REG))])] + "operands[1] = gen_lowpart (QImode, operands[1]);") + +;; These instructions are never faster than the corresponding +;; and/ior/xor operations when using immediate operand, so with +;; 32-bit there's no point. But in 64-bit, we can't hold the +;; relevant immediates within the instruction itself, so operating +;; on bits in the high 32-bits of a register becomes easier. ;; ;; These are slow on Nocona, but fast on Athlon64. We do require the use ;; of btrq and btcq for corner cases of post-reload expansion of absdf and ;; negdf respectively, so they can never be disabled entirely. -(define_insn "*btsq" - [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") +(define_insn "*btsq_imm" + [(set (zero_extract:DI (match_operand:DI 0 "nonimmediate_operand" "+rm") (const_int 1) (match_operand 1 "const_0_to_63_operand" "J")) (const_int 1)) @@ -10959,8 +11110,8 @@ (set_attr "znver1_decode" "double") (set_attr "mode" "DI")]) -(define_insn "*btrq" - [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") +(define_insn "*btrq_imm" + [(set (zero_extract:DI (match_operand:DI 0 "nonimmediate_operand" "+rm") (const_int 1) (match_operand 1 "const_0_to_63_operand" "J")) (const_int 0)) @@ -10972,8 +11123,8 @@ (set_attr "znver1_decode" "double") (set_attr "mode" "DI")]) -(define_insn "*btcq" - [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r") +(define_insn "*btcq_imm" + [(set (zero_extract:DI (match_operand:DI 0 "nonimmediate_operand" "+rm") (const_int 1) (match_operand 1 "const_0_to_63_operand" "J")) (not:DI (zero_extract:DI (match_dup 0) (const_int 1) (match_dup 1)))) @@ -10990,7 +11141,7 @@ (define_peephole2 [(match_scratch:DI 2 "r") (parallel [(set (zero_extract:DI - (match_operand:DI 0 "register_operand") + (match_operand:DI 0 "nonimmediate_operand") (const_int 1) (match_operand 1 "const_0_to_63_operand")) (const_int 1)) @@ -11014,7 +11165,7 @@ (define_peephole2 [(match_scratch:DI 2 "r") (parallel [(set (zero_extract:DI - (match_operand:DI 0 "register_operand") + (match_operand:DI 0 "nonimmediate_operand") (const_int 1) (match_operand 1 "const_0_to_63_operand")) (const_int 0)) @@ -11038,7 +11189,7 @@ (define_peephole2 [(match_scratch:DI 2 "r") (parallel [(set (zero_extract:DI - (match_operand:DI 0 "register_operand") + (match_operand:DI 0 "nonimmediate_operand") (const_int 1) (match_operand 1 "const_0_to_63_operand")) (not:DI (zero_extract:DI @@ -11060,13 +11211,15 @@ } }) +;; %%% bt + (define_insn "*bt" [(set (reg:CCC FLAGS_REG) (compare:CCC (zero_extract:SWI48 (match_operand:SWI48 0 "register_operand" "r") (const_int 1) - (match_operand:SI 1 "nonmemory_operand" "rN")) + (match_operand:SI 1 "nonmemory_operand" "r")) (const_int 0)))] "" { @@ -12632,20 +12785,17 @@ [(set (pc) (if_then_else (ltu (minus (reg SP_REG) (match_operand 0 "register_operand")) - (unspec [(const_int 0)] UNSPEC_STACK_CHECK)) + (match_dup 2)) (label_ref (match_operand 1)) (pc)))] "" { - rtx reg, size, limit; + rtx reg = gen_reg_rtx (Pmode); + + emit_insn (gen_sub3_insn (reg, stack_pointer_rtx, operands[0])); - reg = gen_reg_rtx (Pmode); - size = force_reg (Pmode, operands[0]); - emit_insn (gen_sub3_insn (reg, stack_pointer_rtx, size)); - limit = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), - UNSPEC_STACK_CHECK); - limit = gen_rtx_MEM (Pmode, gen_rtx_CONST (Pmode, limit)); - ix86_expand_branch (GEU, reg, limit, operands[1]); + operands[2] = ix86_split_stack_guard (); + ix86_expand_branch (GEU, reg, operands[2], operands[1]); DONE; }) @@ -13086,8 +13236,6 @@ (set_attr "prefix" "vex") (set_attr "mode" "")]) -(define_mode_attr k [(SI "k") (DI "q")]) - (define_insn "*bmi2_bzhi_3_1" [(set (match_operand:SWI48 0 "register_operand" "=r") (zero_extract:SWI48 @@ -13779,82 +13927,78 @@ (clobber (match_dup 5)) (clobber (reg:CC FLAGS_REG))])]) -;; Segment register for the thread base ptr load -(define_mode_attr tp_seg [(SI "gs") (DI "fs")]) - ;; Load and add the thread base pointer from %:0. -(define_insn "*load_tp_x32" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(const_int 0)] UNSPEC_TP))] - "TARGET_X32" - "mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}" - [(set_attr "type" "imov") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) +(define_insn_and_split "*load_tp_" + [(set (match_operand:PTR 0 "register_operand" "=r") + (unspec:PTR [(const_int 0)] UNSPEC_TP))] + "" + "#" + "" + [(set (match_dup 0) + (match_dup 1))] +{ + addr_space_t as = DEFAULT_TLS_SEG_REG; -(define_insn "*load_tp_x32_zext" + operands[1] = gen_const_mem (mode, const0_rtx); + set_mem_addr_space (operands[1], as); +}) + +(define_insn_and_split "*load_tp_x32_zext" [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (unspec:SI [(const_int 0)] UNSPEC_TP)))] + (zero_extend:DI + (unspec:SI [(const_int 0)] UNSPEC_TP)))] "TARGET_X32" - "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" - [(set_attr "type" "imov") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) + "#" + "" + [(set (match_dup 0) + (zero_extend:DI (match_dup 1)))] +{ + addr_space_t as = DEFAULT_TLS_SEG_REG; -(define_insn "*load_tp_" - [(set (match_operand:P 0 "register_operand" "=r") - (unspec:P [(const_int 0)] UNSPEC_TP))] - "!TARGET_X32" - "mov{}\t{%%:0, %0|%0, PTR :0}" - [(set_attr "type" "imov") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) + operands[1] = gen_const_mem (SImode, const0_rtx); + set_mem_addr_space (operands[1], as); +}) -(define_insn "*add_tp_x32" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) - (match_operand:SI 1 "register_operand" "0"))) +(define_insn_and_split "*add_tp_" + [(set (match_operand:PTR 0 "register_operand" "=r") + (plus:PTR + (unspec:PTR [(const_int 0)] UNSPEC_TP) + (match_operand:PTR 1 "register_operand" "0"))) (clobber (reg:CC FLAGS_REG))] - "TARGET_X32" - "add{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}" - [(set_attr "type" "alu") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) + "" + "#" + "" + [(parallel + [(set (match_dup 0) + (plus:PTR (match_dup 1) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + addr_space_t as = DEFAULT_TLS_SEG_REG; + + operands[2] = gen_const_mem (mode, const0_rtx); + set_mem_addr_space (operands[2], as); +}) -(define_insn "*add_tp_x32_zext" +(define_insn_and_split "*add_tp_x32_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) (match_operand:SI 1 "register_operand" "0")))) (clobber (reg:CC FLAGS_REG))] "TARGET_X32" - "add{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" - [(set_attr "type" "alu") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) + "#" + "" + [(parallel + [(set (match_dup 0) + (zero_extend:DI + (plus:SI (match_dup 1) (match_dup 2)))) + (clobber (reg:CC FLAGS_REG))])] +{ + addr_space_t as = DEFAULT_TLS_SEG_REG; -(define_insn "*add_tp_" - [(set (match_operand:P 0 "register_operand" "=r") - (plus:P (unspec:P [(const_int 0)] UNSPEC_TP) - (match_operand:P 1 "register_operand" "0"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_X32" - "add{}\t{%%:0, %0|%0, PTR :0}" - [(set_attr "type" "alu") - (set_attr "modrm" "0") - (set_attr "length" "7") - (set_attr "memory" "load") - (set_attr "imm_disp" "false")]) + operands[2] = gen_const_mem (SImode, const0_rtx); + set_mem_addr_space (operands[2], as); +}) ;; The Sun linker took the AMD64 TLS spec literally and can only handle ;; %rax as destination of the initial executable code sequence. @@ -15505,7 +15649,7 @@ (unspec:MODEF [(match_operand:MODEF 1 "register_operand" "x,v") (match_operand:SI 2 "const_0_to_15_operand" "n,n")] UNSPEC_ROUND))] - "TARGET_ROUND" + "TARGET_SSE4_1" "@ %vround\t{%2, %1, %d0|%d0, %1, %2} vrndscale\t{%2, %1, %d0|%d0, %1, %2}" @@ -15546,7 +15690,7 @@ { if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH) { - if (TARGET_ROUND) + if (TARGET_SSE4_1) emit_insn (gen_sse4_1_round2 (operands[0], operands[1], GEN_INT (ROUND_MXCSR))); else @@ -15570,7 +15714,7 @@ if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH && !flag_trapping_math && !flag_rounding_math) { - if (TARGET_ROUND) + if (TARGET_SSE4_1) { operands[1] = force_reg (mode, operands[1]); ix86_expand_round_sse4 (operands[0], operands[1]); @@ -15832,12 +15976,13 @@ || TARGET_MIX_SSE_I387) && (flag_fp_int_builtin_inexact || !flag_trapping_math)) || (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH - && (TARGET_ROUND || !flag_trapping_math || flag_fp_int_builtin_inexact))" + && (TARGET_SSE4_1 || !flag_trapping_math + || flag_fp_int_builtin_inexact))" { if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH - && (TARGET_ROUND || !flag_trapping_math || flag_fp_int_builtin_inexact)) + && (TARGET_SSE4_1 || !flag_trapping_math || flag_fp_int_builtin_inexact)) { - if (TARGET_ROUND) + if (TARGET_SSE4_1) emit_insn (gen_sse4_1_round2 (operands[0], operands[1], GEN_INT (ROUND_ | ROUND_NO_EXC))); @@ -18606,6 +18751,18 @@ } [(set_attr "length" "2")]) +(define_insn "ud2" + [(unspec_volatile [(const_int 0)] UNSPECV_UD2)] + "" +{ +#ifdef HAVE_AS_IX86_UD2 + return "ud2"; +#else + return ASM_SHORT "0x0b0f"; +#endif +} + [(set_attr "length" "2")]) + (define_expand "prefetch" [(prefetch (match_operand 0 "address_operand") (match_operand:SI 1 "const_int_operand") @@ -18705,16 +18862,9 @@ { rtx (*insn)(rtx, rtx); -#ifdef TARGET_THREAD_SSP_OFFSET - operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); - insn = (TARGET_LP64 - ? gen_stack_tls_protect_set_di - : gen_stack_tls_protect_set_si); -#else insn = (TARGET_LP64 ? gen_stack_protect_set_di : gen_stack_protect_set_si); -#endif emit_insn (insn (operands[0], operands[1])); DONE; @@ -18730,16 +18880,6 @@ "mov{}\t{%1, %2|%2, %1}\;mov{}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_set_" - [(set (match_operand:PTR 0 "memory_operand" "=m") - (unspec:PTR [(match_operand:PTR 1 "const_int_operand" "i")] - UNSPEC_SP_TLS_SET)) - (set (match_scratch:PTR 2 "=&r") (const_int 0)) - (clobber (reg:CC FLAGS_REG))] - "" - "mov{}\t{%@:%P1, %2|%2, PTR %@:%P1}\;mov{}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" - [(set_attr "type" "multi")]) - (define_expand "stack_protect_test" [(match_operand 0 "memory_operand") (match_operand 1 "memory_operand") @@ -18750,16 +18890,9 @@ rtx (*insn)(rtx, rtx, rtx); -#ifdef TARGET_THREAD_SSP_OFFSET - operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); - insn = (TARGET_LP64 - ? gen_stack_tls_protect_test_di - : gen_stack_tls_protect_test_si); -#else insn = (TARGET_LP64 ? gen_stack_protect_test_di : gen_stack_protect_test_si); -#endif emit_insn (insn (flags, operands[0], operands[1])); @@ -18778,16 +18911,6 @@ "mov{}\t{%1, %3|%3, %1}\;xor{}\t{%2, %3|%3, %2}" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_test_" - [(set (match_operand:CCZ 0 "flags_reg_operand") - (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m") - (match_operand:PTR 2 "const_int_operand" "i")] - UNSPEC_SP_TLS_TEST)) - (clobber (match_scratch:PTR 3 "=r"))] - "" - "mov{}\t{%1, %3|%3, %1}\;xor{}\t{%@:%P2, %3|%3, PTR %@:%P2}" - [(set_attr "type" "multi")]) - (define_insn "sse4_2_crc32" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index adc75f36602a2..81bbc1e2170a1 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -440,7 +440,7 @@ Target RejectNegative Mask(SSEREGPARM) Save Use SSE register passing conventions for SF and DF mode. mstackrealign -Target Report Var(ix86_force_align_arg_pointer) Init(-1) +Target Report Var(ix86_force_align_arg_pointer) Realign stack in prologue. mstack-arg-probe @@ -514,11 +514,11 @@ Target RejectNegative Joined Var(ix86_tune_ctrl_string) Fine grain control of tune features. mno-default -Target RejectNegative Var(ix86_tune_no_default) Init(0) +Target RejectNegative Var(ix86_tune_no_default) Clear all tune features. mdump-tune-features -Target RejectNegative Var(ix86_dump_tunes) Init(0) +Target RejectNegative Var(ix86_dump_tunes) miamcu Target Report Mask(IAMCU) @@ -862,20 +862,20 @@ Target Report Mask(ISA_PREFETCHWT1) Var(ix86_isa_flags) Save Support PREFETCHWT1 built-in functions and code generation. mfentry -Target Report Var(flag_fentry) Init(-1) +Target Report Var(flag_fentry) Emit profiling counter call at function entry before prologue. mrecord-mcount -Target Report Var(flag_record_mcount) Init(0) +Target Report Var(flag_record_mcount) Generate __mcount_loc section with all mcount or __fentry__ calls. mnop-mcount -Target Report Var(flag_nop_mcount) Init(0) +Target Report Var(flag_nop_mcount) Generate mcount/__fentry__ calls as nops. To activate they need to be patched in. mskip-rax-setup -Target Report Var(flag_skip_rax_setup) Init(0) +Target Report Var(flag_skip_rax_setup) Skip setting up RAX register when passing variable arguments. m8bit-idiv @@ -924,8 +924,26 @@ Enum(stack_protector_guard) String(tls) Value(SSP_TLS) EnumValue Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL) +mstack-protector-guard-reg= +Target RejectNegative Joined Var(ix86_stack_protector_guard_reg_str) +Use the given base register for addressing the stack-protector guard. + +TargetVariable +addr_space_t ix86_stack_protector_guard_reg = ADDR_SPACE_GENERIC + +mstack-protector-guard-offset= +Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_offset_str) +Use the given offset for addressing the stack-protector guard. + +TargetVariable +HOST_WIDE_INT ix86_stack_protector_guard_offset = 0 + +mstack-protector-guard-symbol= +Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_symbol_str) +Use the given symbol for addressing the stack-protector guard. + mmitigate-rop -Target Var(flag_mitigate_rop) Init(0) +Target Var(flag_mitigate_rop) Attempt to avoid generating instruction sequences containing ret bytes. mgeneral-regs-only diff --git a/gcc/config/i386/mingw.opt b/gcc/config/i386/mingw.opt index 210c14f549eb0..97a9baa6d7a4f 100644 --- a/gcc/config/i386/mingw.opt +++ b/gcc/config/i386/mingw.opt @@ -28,8 +28,4 @@ Wpedantic-ms-format C ObjC C++ ObjC++ Var(warn_pedantic_ms_format) Init(1) Warning Warn about none ISO msvcrt scanf/printf width extensions. -fset-stack-executable -Common Report Var(flag_setstackexecutable) Init(1) Optimization -For nested functions on stack executable permission is set. - ; Need to retain blank line above. diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 7a1789f0b473f..b3f3633e96449 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -641,7 +641,7 @@ [(set (match_dup 0) (match_dup 1))] "operands[1] = adjust_address (operands[1], SFmode, 4);") -(define_expand "vec_extractv2sf" +(define_expand "vec_extractv2sfsf" [(match_operand:SF 0 "register_operand") (match_operand:V2SF 1 "register_operand") (match_operand 2 "const_int_operand")] @@ -652,7 +652,7 @@ DONE; }) -(define_expand "vec_initv2sf" +(define_expand "vec_initv2sfsf" [(match_operand:V2SF 0 "register_operand") (match_operand 1)] "TARGET_SSE" @@ -1344,7 +1344,7 @@ operands[1] = adjust_address (operands[1], SImode, INTVAL (operands[2]) * 4); }) -(define_expand "vec_extractv2si" +(define_expand "vec_extractv2sisi" [(match_operand:SI 0 "register_operand") (match_operand:V2SI 1 "register_operand") (match_operand 2 "const_int_operand")] @@ -1355,7 +1355,7 @@ DONE; }) -(define_expand "vec_initv2si" +(define_expand "vec_initv2sisi" [(match_operand:V2SI 0 "register_operand") (match_operand 1)] "TARGET_SSE" @@ -1375,7 +1375,7 @@ DONE; }) -(define_expand "vec_extractv4hi" +(define_expand "vec_extractv4hihi" [(match_operand:HI 0 "register_operand") (match_operand:V4HI 1 "register_operand") (match_operand 2 "const_int_operand")] @@ -1386,7 +1386,7 @@ DONE; }) -(define_expand "vec_initv4hi" +(define_expand "vec_initv4hihi" [(match_operand:V4HI 0 "register_operand") (match_operand 1)] "TARGET_SSE" @@ -1406,7 +1406,7 @@ DONE; }) -(define_expand "vec_extractv8qi" +(define_expand "vec_extractv8qiqi" [(match_operand:QI 0 "register_operand") (match_operand:V8QI 1 "register_operand") (match_operand 2 "const_int_operand")] @@ -1417,7 +1417,7 @@ DONE; }) -(define_expand "vec_initv8qi" +(define_expand "vec_initv8qiqi" [(match_operand:V8QI 0 "register_operand") (match_operand 1)] "TARGET_SSE" diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 56b7f436d5db7..4f2328f136801 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -658,13 +658,21 @@ ;; Mapping of vector modes to a vector mode of half size (define_mode_attr ssehalfvecmode - [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI") + [(V64QI "V32QI") (V32HI "V16HI") (V16SI "V8SI") (V8DI "V4DI") (V4TI "V2TI") (V32QI "V16QI") (V16HI "V8HI") (V8SI "V4SI") (V4DI "V2DI") (V16QI "V8QI") (V8HI "V4HI") (V4SI "V2SI") (V16SF "V8SF") (V8DF "V4DF") (V8SF "V4SF") (V4DF "V2DF") (V4SF "V2SF")]) +(define_mode_attr ssehalfvecmodelower + [(V64QI "v32qi") (V32HI "v16hi") (V16SI "v8si") (V8DI "v4di") (V4TI "v2ti") + (V32QI "v16qi") (V16HI "v8hi") (V8SI "v4si") (V4DI "v2di") + (V16QI "v8qi") (V8HI "v4hi") (V4SI "v2si") + (V16SF "v8sf") (V8DF "v4df") + (V8SF "v4sf") (V4DF "v2df") + (V4SF "v2sf")]) + ;; Mapping of vector modes ti packed single mode of the same size (define_mode_attr ssePSmode [(V16SI "V16SF") (V8DF "V16SF") @@ -690,6 +698,16 @@ (V8DF "DF") (V4DF "DF") (V2DF "DF") (V4TI "TI") (V2TI "TI")]) +;; Mapping of vector modes back to the scalar modes +(define_mode_attr ssescalarmodelower + [(V64QI "qi") (V32QI "qi") (V16QI "qi") + (V32HI "hi") (V16HI "hi") (V8HI "hi") + (V16SI "si") (V8SI "si") (V4SI "si") + (V8DI "di") (V4DI "di") (V2DI "di") + (V16SF "sf") (V8SF "sf") (V4SF "sf") + (V8DF "df") (V4DF "df") (V2DF "df") + (V4TI "ti") (V2TI "ti")]) + ;; Mapping of vector modes to the 128bit modes (define_mode_attr ssexmmmode [(V64QI "V16QI") (V32QI "V16QI") (V16QI "V16QI") @@ -2356,7 +2374,7 @@ { rtx tmp = gen_reg_rtx (V8DFmode); ix86_expand_reduc (gen_addv8df3, tmp, operands[1]); - emit_insn (gen_vec_extractv8df (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extractv8dfdf (operands[0], tmp, const0_rtx)); DONE; }) @@ -2371,7 +2389,7 @@ emit_insn (gen_avx_haddv4df3 (tmp, operands[1], operands[1])); emit_insn (gen_avx_vperm2f128v4df3 (tmp2, tmp, tmp, GEN_INT (1))); emit_insn (gen_addv4df3 (vec_res, tmp, tmp2)); - emit_insn (gen_vec_extractv4df (operands[0], vec_res, const0_rtx)); + emit_insn (gen_vec_extractv4dfdf (operands[0], vec_res, const0_rtx)); DONE; }) @@ -2382,7 +2400,7 @@ { rtx tmp = gen_reg_rtx (V2DFmode); emit_insn (gen_sse3_haddv2df3 (tmp, operands[1], operands[1])); - emit_insn (gen_vec_extractv2df (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extractv2dfdf (operands[0], tmp, const0_rtx)); DONE; }) @@ -2393,7 +2411,7 @@ { rtx tmp = gen_reg_rtx (V16SFmode); ix86_expand_reduc (gen_addv16sf3, tmp, operands[1]); - emit_insn (gen_vec_extractv16sf (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extractv16sfsf (operands[0], tmp, const0_rtx)); DONE; }) @@ -2409,7 +2427,7 @@ emit_insn (gen_avx_haddv8sf3 (tmp2, tmp, tmp)); emit_insn (gen_avx_vperm2f128v8sf3 (tmp, tmp2, tmp2, GEN_INT (1))); emit_insn (gen_addv8sf3 (vec_res, tmp, tmp2)); - emit_insn (gen_vec_extractv8sf (operands[0], vec_res, const0_rtx)); + emit_insn (gen_vec_extractv8sfsf (operands[0], vec_res, const0_rtx)); DONE; }) @@ -2427,7 +2445,7 @@ } else ix86_expand_reduc (gen_addv4sf3, vec_res, operands[1]); - emit_insn (gen_vec_extractv4sf (operands[0], vec_res, const0_rtx)); + emit_insn (gen_vec_extractv4sfsf (operands[0], vec_res, const0_rtx)); DONE; }) @@ -2449,7 +2467,8 @@ { rtx tmp = gen_reg_rtx (mode); ix86_expand_reduc (gen_3, tmp, operands[1]); - emit_insn (gen_vec_extract (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], tmp, + const0_rtx)); DONE; }) @@ -2461,7 +2480,8 @@ { rtx tmp = gen_reg_rtx (mode); ix86_expand_reduc (gen_3, tmp, operands[1]); - emit_insn (gen_vec_extract (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], tmp, + const0_rtx)); DONE; }) @@ -2473,7 +2493,8 @@ { rtx tmp = gen_reg_rtx (mode); ix86_expand_reduc (gen_3, tmp, operands[1]); - emit_insn (gen_vec_extract (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extract (operands[0], tmp, + const0_rtx)); DONE; }) @@ -2485,7 +2506,7 @@ { rtx tmp = gen_reg_rtx (V8HImode); ix86_expand_reduc (gen_uminv8hi3, tmp, operands[1]); - emit_insn (gen_vec_extractv8hi (operands[0], tmp, const0_rtx)); + emit_insn (gen_vec_extractv8hihi (operands[0], tmp, const0_rtx)); DONE; }) @@ -7881,7 +7902,7 @@ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")]) -(define_expand "vec_extract" +(define_expand "vec_extract" [(match_operand: 0 "register_operand") (match_operand:VEC_EXTRACT_MODE 1 "register_operand") (match_operand 2 "const_int_operand")] @@ -7892,6 +7913,19 @@ DONE; }) +(define_expand "vec_extract" + [(match_operand: 0 "nonimmediate_operand") + (match_operand:V_512 1 "register_operand") + (match_operand 2 "const_0_to_1_operand")] + "TARGET_AVX512F" +{ + if (INTVAL (operands[2])) + emit_insn (gen_vec_extract_hi_ (operands[0], operands[1])); + else + emit_insn (gen_vec_extract_lo_ (operands[0], operands[1])); + DONE; +}) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parallel double-precision floating point element swizzling @@ -15571,7 +15605,7 @@ [(match_operand:VF_128_256 1 "vector_operand" "YrBm,*xBm,xm") (match_operand:SI 2 "const_0_to_15_operand" "n,n,n")] UNSPEC_ROUND))] - "TARGET_ROUND" + "TARGET_SSE4_1" "%vround\t{%2, %1, %0|%0, %1, %2}" [(set_attr "isa" "noavx,noavx,avx") (set_attr "type" "ssecvt") @@ -15585,7 +15619,7 @@ [(match_operand: 0 "register_operand") (match_operand:VF1_128_256 1 "vector_operand") (match_operand:SI 2 "const_0_to_15_operand")] - "TARGET_ROUND" + "TARGET_SSE4_1" { rtx tmp = gen_reg_rtx (mode); @@ -15624,7 +15658,7 @@ (match_operand:VF2 1 "vector_operand") (match_operand:VF2 2 "vector_operand") (match_operand:SI 3 "const_0_to_15_operand")] - "TARGET_ROUND" + "TARGET_SSE4_1" { rtx tmp0, tmp1; @@ -15666,7 +15700,7 @@ UNSPEC_ROUND) (match_operand:VF_128 1 "register_operand" "0,0,x,v") (const_int 1)))] - "TARGET_ROUND" + "TARGET_SSE4_1" "@ round\t{%3, %2, %0|%0, %2, %3} round\t{%3, %2, %0|%0, %2, %3} @@ -15689,7 +15723,7 @@ (unspec:VF [(match_dup 3) (match_dup 4)] UNSPEC_ROUND))] - "TARGET_ROUND && !flag_trapping_math" + "TARGET_SSE4_1 && !flag_trapping_math" { machine_mode scalar_mode; const struct real_format *fmt; @@ -15717,7 +15751,7 @@ (define_expand "round2_sfix" [(match_operand: 0 "register_operand") (match_operand:VF1 1 "register_operand")] - "TARGET_ROUND && !flag_trapping_math" + "TARGET_SSE4_1 && !flag_trapping_math" { rtx tmp = gen_reg_rtx (mode); @@ -15732,7 +15766,7 @@ [(match_operand: 0 "register_operand") (match_operand:VF2 1 "register_operand") (match_operand:VF2 2 "register_operand")] - "TARGET_ROUND && !flag_trapping_math" + "TARGET_SSE4_1 && !flag_trapping_math" { rtx tmp0, tmp1; @@ -16693,7 +16727,7 @@ for (i = 0; i < ; i++) RTVEC_ELT (vs, i) = op2; - emit_insn (gen_vec_init (reg, par)); + emit_insn (gen_vec_init (reg, par)); emit_insn (gen_xop_vrotl3 (operands[0], operands[1], reg)); DONE; } @@ -16725,7 +16759,7 @@ for (i = 0; i < ; i++) RTVEC_ELT (vs, i) = op2; - emit_insn (gen_vec_init (reg, par)); + emit_insn (gen_vec_init (reg, par)); emit_insn (gen_neg2 (neg, reg)); emit_insn (gen_xop_vrotl3 (operands[0], operands[1], neg)); DONE; @@ -17019,7 +17053,7 @@ XVECEXP (par, 0, i) = operands[2]; tmp = gen_reg_rtx (V16QImode); - emit_insn (gen_vec_initv16qi (tmp, par)); + emit_insn (gen_vec_initv16qiqi (tmp, par)); if (negate) emit_insn (gen_negv16qi2 (tmp, tmp)); @@ -17055,7 +17089,7 @@ for (i = 0; i < 2; i++) XVECEXP (par, 0, i) = operands[2]; - emit_insn (gen_vec_initv2di (reg, par)); + emit_insn (gen_vec_initv2didi (reg, par)); if (negate) emit_insn (gen_negv2di2 (reg, reg)); @@ -18775,7 +18809,7 @@ mode); }) -;; Modes handled by vec_init patterns. +;; Modes handled by vec_init expanders. (define_mode_iterator VEC_INIT_MODE [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI @@ -18785,7 +18819,18 @@ (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2") (V4TI "TARGET_AVX512F") (V2TI "TARGET_AVX")]) -(define_expand "vec_init" +;; Likewise, but for initialization from half sized vectors. +;; Thus, these are all VEC_INIT_MODE modes except V2??. +(define_mode_iterator VEC_INIT_HALF_MODE + [(V64QI "TARGET_AVX512F") (V32QI "TARGET_AVX") V16QI + (V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX") V8HI + (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI + (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") + (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF + (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") + (V4TI "TARGET_AVX512F")]) + +(define_expand "vec_init" [(match_operand:VEC_INIT_MODE 0 "register_operand") (match_operand 1)] "TARGET_SSE" @@ -18794,6 +18839,15 @@ DONE; }) +(define_expand "vec_init" + [(match_operand:VEC_INIT_HALF_MODE 0 "register_operand") + (match_operand 1)] + "TARGET_SSE" +{ + ix86_expand_vector_init (false, operands[0], operands[1]); + DONE; +}) + (define_insn "_ashrv" [(set (match_operand:VI48_AVX512F_AVX512VL 0 "register_operand" "=v") (ashiftrt:VI48_AVX512F_AVX512VL diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 8272c7fddc1ff..405f74a75974c 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "emit-rtl.h" #include "cgraph.h" #include "lto-streamer.h" diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index c8e4c74bbdbe5..571c204302211 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -232,8 +233,8 @@ static bool ia64_in_small_data_p (const_tree); static void process_epilogue (FILE *, rtx, bool, bool); static bool ia64_assemble_integer (rtx, unsigned int, int); -static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT); -static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT); +static void ia64_output_function_prologue (FILE *); +static void ia64_output_function_epilogue (FILE *); static void ia64_output_function_end_prologue (FILE *); static void ia64_print_operand (FILE *, rtx, int); @@ -4277,7 +4278,7 @@ ia64_assemble_integer (rtx x, unsigned int size, int aligned_p) /* Emit the function prologue. */ static void -ia64_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +ia64_output_function_prologue (FILE *file) { int mask, grsave, grsave_prev; @@ -4355,8 +4356,7 @@ ia64_output_function_end_prologue (FILE *file) /* Emit the function epilogue. */ static void -ia64_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +ia64_output_function_epilogue (FILE *) { int i; diff --git a/gcc/config/ia64/vect.md b/gcc/config/ia64/vect.md index a565df53bfa80..8e76864a77f12 100644 --- a/gcc/config/ia64/vect.md +++ b/gcc/config/ia64/vect.md @@ -1015,7 +1015,7 @@ } [(set_attr "itanium_class" "mmshf")]) -(define_expand "vec_initv2si" +(define_expand "vec_initv2sisi" [(match_operand:V2SI 0 "gr_register_operand" "") (match_operand 1 "" "")] "" @@ -1299,7 +1299,7 @@ "fselect %0 = %F2, %F3, %1" [(set_attr "itanium_class" "fmisc")]) -(define_expand "vec_initv2sf" +(define_expand "vec_initv2sfsf" [(match_operand:V2SF 0 "fr_register_operand" "") (match_operand 1 "" "")] "" @@ -1483,7 +1483,7 @@ operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1])); }) -(define_expand "vec_extractv2sf" +(define_expand "vec_extractv2sfsf" [(set (match_operand:SF 0 "register_operand" "") (unspec:SF [(match_operand:V2SF 1 "register_operand" "") (match_operand:DI 2 "const_int_operand" "")] diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index 99abd76c5a696..5a92164ef053f 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/lm32/lm32.c b/gcc/config/lm32/lm32.c index 2231412e56676..214cc0ac5fde6 100644 --- a/gcc/config/lm32/lm32.c +++ b/gcc/config/lm32/lm32.c @@ -26,6 +26,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index b23f5aaf21a78..95e97abf53397 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index 4efb4b9c28726..ae3738823783a 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -28,6 +28,7 @@ #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "insn-config.h" #include "emit-rtl.h" #include "recog.h" @@ -69,8 +70,8 @@ static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *); static void m32r_print_operand (FILE *, rtx, int); static void m32r_print_operand_address (FILE *, machine_mode, rtx); static bool m32r_print_operand_punct_valid_p (unsigned char code); -static void m32r_output_function_prologue (FILE *, HOST_WIDE_INT); -static void m32r_output_function_epilogue (FILE *, HOST_WIDE_INT); +static void m32r_output_function_prologue (FILE *); +static void m32r_output_function_epilogue (FILE *); static void m32r_file_start (void); @@ -1743,7 +1744,7 @@ m32r_expand_prologue (void) m32r_compute_frame_size which calculates the prolog size. */ static void -m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size) +m32r_output_function_prologue (FILE * file) { enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl); @@ -1752,7 +1753,7 @@ m32r_output_function_prologue (FILE * file, HOST_WIDE_INT size) fprintf (file, "\t%s interrupt handler\n", ASM_COMMENT_START); if (! current_frame_info.initialized) - m32r_compute_frame_size (size); + m32r_compute_frame_size (get_frame_size ()); /* This is only for the human reader. */ fprintf (file, @@ -1879,8 +1880,7 @@ m32r_expand_epilogue (void) and regs. */ static void -m32r_output_function_epilogue (FILE * file ATTRIBUTE_UNUSED, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +m32r_output_function_epilogue (FILE *) { /* Reset state info for each function. */ current_frame_info = zero_frame_info; diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index c14ce86d8102b..89726655122e5 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "backend.h" #include "cfghooks.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "rtl.h" #include "df.h" #include "alias.h" diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index c4b7c4cf94f66..e67376fb6aa09 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -28,6 +28,7 @@ #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "emit-rtl.h" #include "diagnostic-core.h" #include "stor-layout.h" diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 15ceac0b346dd..04121c816ed6f 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -26,6 +26,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" @@ -2657,7 +2659,7 @@ save_restore_insns (int prologue) /* Set up the stack and frame (if desired) for the function. */ static void -microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +microblaze_function_prologue (FILE * file) { const char *fnname; long fsiz = current_frame_info.total_size; @@ -2953,8 +2955,7 @@ microblaze_expand_prologue (void) #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST)) static void -microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +microblaze_function_epilogue (FILE *file) { const char *fnname; diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md index 85842551b0d29..b48dfa0dc713d 100644 --- a/gcc/config/mips/loongson.md +++ b/gcc/config/mips/loongson.md @@ -119,7 +119,7 @@ ;; Initialization of a vector. -(define_expand "vec_init" +(define_expand "vec_init" [(set (match_operand:VWHB 0 "register_operand") (match_operand 1 ""))] "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" diff --git a/gcc/config/mips/mips-msa.md b/gcc/config/mips/mips-msa.md index c80be471026cf..87d889d729632 100644 --- a/gcc/config/mips/mips-msa.md +++ b/gcc/config/mips/mips-msa.md @@ -231,7 +231,7 @@ (V4SI "uimm5") (V2DI "uimm6")]) -(define_expand "vec_init" +(define_expand "vec_init" [(match_operand:MSA 0 "register_operand") (match_operand:MSA 1 "")] "ISA_HAS_MSA" @@ -311,7 +311,7 @@ DONE; }) -(define_expand "vec_extract" +(define_expand "vec_extract" [(match_operand: 0 "register_operand") (match_operand:IMSA 1 "register_operand") (match_operand 2 "const__operand")] @@ -329,7 +329,7 @@ DONE; }) -(define_expand "vec_extract" +(define_expand "vec_extract" [(match_operand: 0 "register_operand") (match_operand:FMSA 1 "register_operand") (match_operand 2 "const__operand")] diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md index 64733984170b4..81820b13b11c8 100644 --- a/gcc/config/mips/mips-ps-3d.md +++ b/gcc/config/mips/mips-ps-3d.md @@ -254,7 +254,7 @@ }) ; vec_init -(define_expand "vec_initv2sf" +(define_expand "vec_initv2sfsf" [(match_operand:V2SF 0 "register_operand") (match_operand:V2SF 1 "")] "TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT" @@ -282,7 +282,7 @@ ;; emulated. There is no other way to get a vector mode bitfield extract ;; currently. -(define_insn "vec_extractv2sf" +(define_insn "vec_extractv2sfsf" [(set (match_operand:SF 0 "register_operand" "=f") (vec_select:SF (match_operand:V2SF 1 "register_operand" "f") (parallel @@ -379,7 +379,7 @@ rtx temp = gen_reg_rtx (V2SFmode); emit_insn (gen_mips_addr_ps (temp, operands[1], operands[1])); rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; - emit_insn (gen_vec_extractv2sf (operands[0], temp, lane)); + emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); DONE; }) @@ -757,7 +757,7 @@ rtx temp = gen_reg_rtx (V2SFmode); mips_expand_vec_reduc (temp, operands[1], gen_sminv2sf3); rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; - emit_insn (gen_vec_extractv2sf (operands[0], temp, lane)); + emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); DONE; }) @@ -769,6 +769,6 @@ rtx temp = gen_reg_rtx (V2SFmode); mips_expand_vec_reduc (temp, operands[1], gen_smaxv2sf3); rtx lane = BYTES_BIG_ENDIAN ? const1_rtx : const0_rtx; - emit_insn (gen_vec_extractv2sf (operands[0], temp, lane)); + emit_insn (gen_vec_extractv2sfsf (operands[0], temp, lane)); DONE; }) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 6bfd86a07af4b..563f74b74f06c 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -11721,7 +11722,7 @@ mips_output_cplocal (void) /* Implement TARGET_OUTPUT_FUNCTION_PROLOGUE. */ static void -mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +mips_output_function_prologue (FILE *file) { const char *fnname; @@ -11816,8 +11817,7 @@ mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) /* Implement TARGET_OUTPUT_FUNCTION_EPILOGUE. */ static void -mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +mips_output_function_epilogue (FILE *) { const char *fnname; diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 971af6f8e097d..f45c3eb98ce1f 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -917,6 +917,11 @@ (V16QI "QI") (V8HI "HI") (V4SI "SI") (V2DI "DI") (V2DF "DF")]) +;; As above, but in lower case. +(define_mode_attr unitmode [(SF "sf") (DF "df") (V2SF "sf") (V4SF "sf") + (V16QI "qi") (V8QI "qi") (V8HI "hi") (V4HI "hi") + (V4SI "si") (V2SI "si") (V2DI "di") (V2DF "df")]) + ;; This attribute gives the integer mode that has the same size as a ;; fixed-point mode. (define_mode_attr IMODE [(QQ "QI") (HQ "HI") (SQ "SI") (DQ "DI") diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index 9849c19e0766b..c2cef018e3ff1 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" @@ -125,9 +127,9 @@ static struct machine_function *mmix_init_machine_status (void); static void mmix_encode_section_info (tree, rtx, int); static const char *mmix_strip_name_encoding (const char *); static void mmix_emit_sp_add (HOST_WIDE_INT offset); -static void mmix_target_asm_function_prologue (FILE *, HOST_WIDE_INT); +static void mmix_target_asm_function_prologue (FILE *); static void mmix_target_asm_function_end_prologue (FILE *); -static void mmix_target_asm_function_epilogue (FILE *, HOST_WIDE_INT); +static void mmix_target_asm_function_epilogue (FILE *); static reg_class_t mmix_preferred_reload_class (rtx, reg_class_t); static reg_class_t mmix_preferred_output_reload_class (rtx, reg_class_t); static bool mmix_legitimate_address_p (machine_mode, rtx, bool); @@ -819,8 +821,7 @@ mmix_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, mmix_reorg. */ static void -mmix_target_asm_function_prologue (FILE *stream ATTRIBUTE_UNUSED, - HOST_WIDE_INT framesize ATTRIBUTE_UNUSED) +mmix_target_asm_function_prologue (FILE *) { cfun->machine->in_prologue = 1; } @@ -878,8 +879,7 @@ mmix_reorg (void) /* TARGET_ASM_FUNCTION_EPILOGUE. */ static void -mmix_target_asm_function_epilogue (FILE *stream, - HOST_WIDE_INT locals_size ATTRIBUTE_UNUSED) +mmix_target_asm_function_epilogue (FILE *stream) { /* Emit an \n for readability of the generated assembly. */ fputc ('\n', stream); diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 301207fa66a33..f46caac7e9484 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "cfghooks.h" #include "cfgloop.h" #include "df.h" diff --git a/gcc/config/moxie/moxie.c b/gcc/config/moxie/moxie.c index 70d6d7e2eaf47..19cd83f519361 100644 --- a/gcc/config/moxie/moxie.c +++ b/gcc/config/moxie/moxie.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "regs.h" #include "memmodel.h" diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 6acab1e70cb69..48fc12d9a913e 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -25,6 +25,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "gimple-expr.h" #include "df.h" #include "memmodel.h" @@ -1902,6 +1904,10 @@ msp430_attr (tree * node, if (! TREE_PUBLIC (* node)) message = "interrupt handlers cannot be static"; + + /* Ensure interrupt handlers never get optimised out. */ + TREE_USED (* node) = 1; + DECL_PRESERVE_P (* node) = 1; } else if (TREE_NAME_EQ (name, ATTR_REENT)) { @@ -2057,7 +2063,7 @@ const struct attribute_spec msp430_attribute_table[] = #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function static void -msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED) +msp430_start_function (FILE *outfile) { int r, n; diff --git a/gcc/config/nds32/nds32-isr.c b/gcc/config/nds32/nds32-isr.c index 29e94d004c6ff..7d7b9e27ca6c4 100644 --- a/gcc/config/nds32/nds32-isr.c +++ b/gcc/config/nds32/nds32-isr.c @@ -27,6 +27,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "diagnostic-core.h" #include "output.h" diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 705d223e49683..48344ddb4b3da 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -27,6 +27,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" @@ -1500,8 +1502,7 @@ nds32_function_value_regno_p (const unsigned int regno) /* The content produced from this function will be placed before prologue body. */ static void -nds32_asm_function_prologue (FILE *file, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +nds32_asm_function_prologue (FILE *file) { int r; const char *func_name; @@ -1618,8 +1619,7 @@ nds32_asm_function_begin_epilogue (FILE *file) /* The content produced from this function will be placed after epilogue body. */ static void -nds32_asm_function_epilogue (FILE *file, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +nds32_asm_function_epilogue (FILE *file) { fprintf (file, "\t! END EPILOGUE\n"); } diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c index 2fc9a080402fa..0a4ce3886146c 100644 --- a/gcc/config/nios2/nios2.c +++ b/gcc/config/nios2/nios2.c @@ -27,6 +27,8 @@ #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" @@ -2798,7 +2800,7 @@ nios2_asm_file_end (void) /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */ static void -nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +nios2_asm_function_prologue (FILE *file) { if (flag_verbose_asm || flag_debug_asm) { diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 208b11555f2c2..8babac75bc304 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -62,6 +62,7 @@ #include "internal-fn.h" #include "gimple-iterator.h" #include "stringpool.h" +#include "attribs.h" #include "tree-vrp.h" #include "tree-ssa-operands.h" #include "tree-ssanames.h" @@ -180,6 +181,10 @@ nvptx_option_override (void) if (!global_options_set.x_flag_no_common) flag_no_common = 1; + /* The patch area requires nops, which we don't have. */ + if (function_entry_patch_area_size > 0) + sorry ("not generating patch area, nops not supported"); + /* Assumes that it will see only hard registers. */ flag_var_tracking = 0; @@ -207,17 +212,6 @@ nvptx_option_override (void) target_flags |= MASK_SOFT_STACK | MASK_UNIFORM_SIMT; } -/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */ - -static void -nvptx_override_options_after_change (void) -{ - /* This is a workaround for PR81430 - nvptx acceleration compilation broken - because of running pass_partition_blocks. This should be dealt with in the - common code, not in the target. */ - flag_reorder_blocks_and_partition = 0; -} - /* Return a ptx type for MODE. If PROMOTE, then use .u32 for QImode to deal with ptx ideosyncracies. */ @@ -5072,7 +5066,9 @@ nvptx_lockless_update (location_t loc, gimple_stmt_iterator *gsi, *gsi = gsi_for_stmt (gsi_stmt (*gsi)); post_edge->flags ^= EDGE_TRUE_VALUE | EDGE_FALLTHRU; + post_edge->probability = profile_probability::even (); edge loop_edge = make_edge (loop_bb, loop_bb, EDGE_FALSE_VALUE); + loop_edge->probability = profile_probability::even (); set_immediate_dominator (CDI_DOMINATORS, loop_bb, pre_bb); set_immediate_dominator (CDI_DOMINATORS, post_bb, loop_bb); @@ -5145,7 +5141,9 @@ nvptx_lockfull_update (location_t loc, gimple_stmt_iterator *gsi, /* Create the lock loop ... */ locked_edge->flags ^= EDGE_TRUE_VALUE | EDGE_FALLTHRU; - make_edge (lock_bb, lock_bb, EDGE_FALSE_VALUE); + locked_edge->probability = profile_probability::even (); + edge loop_edge = make_edge (lock_bb, lock_bb, EDGE_FALSE_VALUE); + loop_edge->probability = profile_probability::even (); set_immediate_dominator (CDI_DOMINATORS, lock_bb, entry_bb); set_immediate_dominator (CDI_DOMINATORS, update_bb, lock_bb); @@ -5518,9 +5516,6 @@ nvptx_data_alignment (const_tree type, unsigned int basic_align) #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE nvptx_option_override -#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE -#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE nvptx_override_options_after_change - #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE nvptx_attribute_table diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 2a78018650c24..071cdb521ed6a 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "regs.h" #include "emit-rtl.h" @@ -115,9 +116,9 @@ static void set_reg_plus_d (int, int, HOST_WIDE_INT, int); static rtx pa_function_value (const_tree, const_tree, bool); static rtx pa_libcall_value (machine_mode, const_rtx); static bool pa_function_value_regno_p (const unsigned int); -static void pa_output_function_prologue (FILE *, HOST_WIDE_INT); +static void pa_output_function_prologue (FILE *); static void update_total_code_bytes (unsigned int); -static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT); +static void pa_output_function_epilogue (FILE *); static int pa_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int); static int pa_adjust_priority (rtx_insn *, int); static int pa_issue_rate (void); @@ -3821,15 +3822,6 @@ pa_compute_frame_size (HOST_WIDE_INT size, int *fregs_live) & ~(PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1)); } -/* Generate the assembly code for function entry. FILE is a stdio - stream to output the code to. SIZE is an int: how many units of - temporary storage to allocate. - - Refer to the array `regs_ever_live' to determine which registers to - save; `regs_ever_live[I]' is nonzero if register number I is ever - used in the function. This function is responsible for knowing - which registers should not be saved even if used. */ - /* On HP-PA, move-double insns between fpu and cpu need an 8-byte block of memory. If any fpu reg is used in the function, we allocate such a block here, at the bottom of the frame, just in case it's needed. @@ -3839,7 +3831,7 @@ pa_compute_frame_size (HOST_WIDE_INT size, int *fregs_live) to do this is made in regclass.c. */ static void -pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +pa_output_function_prologue (FILE *file) { /* The function's label and associated .PROC must never be separated and must be output *after* any profiling declarations @@ -4253,7 +4245,7 @@ update_total_code_bytes (unsigned int nbytes) adjustments before returning. */ static void -pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) +pa_output_function_epilogue (FILE *file) { rtx_insn *insn = get_last_insn (); bool extra_nop; diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index c2ce6e8abe5d9..fbbb34390f4fc 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "df.h" #include "memmodel.h" #include "tm_p.h" diff --git a/gcc/config/powerpcspe/altivec.md b/gcc/config/powerpcspe/altivec.md index 649f1810d1685..e98309a8ad416 100644 --- a/gcc/config/powerpcspe/altivec.md +++ b/gcc/config/powerpcspe/altivec.md @@ -301,7 +301,7 @@ for (i = 0; i < num_elements; i++) RTVEC_ELT (v, i) = constm1_rtx; - emit_insn (gen_vec_initv4si (dest, gen_rtx_PARALLEL (mode, v))); + emit_insn (gen_vec_initv4sisi (dest, gen_rtx_PARALLEL (mode, v))); emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, dest, dest))); DONE; }) @@ -2222,7 +2222,7 @@ RTVEC_ELT (v, 2) = GEN_INT (mask_val); RTVEC_ELT (v, 3) = GEN_INT (mask_val); - emit_insn (gen_vec_initv4si (mask, gen_rtx_PARALLEL (V4SImode, v))); + emit_insn (gen_vec_initv4sisi (mask, gen_rtx_PARALLEL (V4SImode, v))); emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2], gen_lowpart (V4SFmode, mask))); DONE; @@ -3014,7 +3014,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 0); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3050,7 +3050,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 6 : 17); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3086,7 +3086,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 8); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3122,7 +3122,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3363,7 +3363,7 @@ = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 17 : 15 - 2 * i); } - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_altivec_vmulesb (even, operands[1], operands[2])); emit_insn (gen_altivec_vmulosb (odd, operands[1], operands[2])); emit_insn (gen_altivec_vperm_v8hiv16qi (operands[0], even, odd, mask)); diff --git a/gcc/config/powerpcspe/paired.md b/gcc/config/powerpcspe/paired.md index 09123eec8871a..e12f07fc9b8a4 100644 --- a/gcc/config/powerpcspe/paired.md +++ b/gcc/config/powerpcspe/paired.md @@ -377,7 +377,7 @@ "ps_muls1 %0, %1, %2" [(set_attr "type" "fp")]) -(define_expand "vec_initv2sf" +(define_expand "vec_initv2sfsf" [(match_operand:V2SF 0 "gpc_reg_operand" "=f") (match_operand 1 "" "")] "TARGET_PAIRED_FLOAT" diff --git a/gcc/config/powerpcspe/powerpcspe.c b/gcc/config/powerpcspe/powerpcspe.c index b94afd5ca2e5e..5a92cd090698b 100644 --- a/gcc/config/powerpcspe/powerpcspe.c +++ b/gcc/config/powerpcspe/powerpcspe.c @@ -31,6 +31,7 @@ #include "df.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "expmed.h" #include "optabs.h" #include "regs.h" @@ -30598,8 +30599,7 @@ rs6000_output_savres_externs (FILE *file) /* Write function prologue. */ static void -rs6000_output_function_prologue (FILE *file, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +rs6000_output_function_prologue (FILE *file) { if (!cfun->is_thunk) rs6000_output_savres_externs (file); @@ -31789,8 +31789,7 @@ rs6000_emit_epilogue (int sibcall) /* Write function epilogue. */ static void -rs6000_output_function_epilogue (FILE *file, - HOST_WIDE_INT size ATTRIBUTE_UNUSED) +rs6000_output_function_epilogue (FILE *file) { #if TARGET_MACHO macho_branch_islands (); diff --git a/gcc/config/powerpcspe/vector.md b/gcc/config/powerpcspe/vector.md index e6489a861cdd4..6c43186f8aa62 100644 --- a/gcc/config/powerpcspe/vector.md +++ b/gcc/config/powerpcspe/vector.md @@ -74,6 +74,16 @@ (V1TI "TI") (TI "TI")]) +;; As above, but in lower case +(define_mode_attr VEC_base_l [(V16QI "qi") + (V8HI "hi") + (V4SI "si") + (V2DI "di") + (V4SF "sf") + (V2DF "df") + (V1TI "ti") + (TI "ti")]) + ;; Same size integer type for floating point data (define_mode_attr VEC_int [(V4SF "v4si") (V2DF "v2di")]) @@ -1017,7 +1027,7 @@ ;; Vector initialization, set, extract -(define_expand "vec_init" +(define_expand "vec_init" [(match_operand:VEC_E 0 "vlogical_operand" "") (match_operand:VEC_E 1 "" "")] "VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)" @@ -1036,7 +1046,7 @@ DONE; }) -(define_expand "vec_extract" +(define_expand "vec_extract" [(match_operand: 0 "register_operand" "") (match_operand:VEC_E 1 "vlogical_operand" "") (match_operand 2 "const_int_operand" "")] diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 57b2edbcb4302..cbf2f79bc4d83 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -31,6 +31,8 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "alias.h" #include "tree.h" +#include "stringpool.h" +#include "attribs.h" #include "varasm.h" #include "stor-layout.h" #include "calls.h" diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 460775cb99590..9592cd9ecb97a 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -29,6 +29,7 @@ #include "memmodel.h" #include "tm_p.h" #include "stringpool.h" +#include "attribs.h" #include "optabs.h" #include "emit-rtl.h" #include "recog.h" @@ -1552,7 +1553,7 @@ rl78_expand_eh_epilogue (rtx x ATTRIBUTE_UNUSED) this to insert a comment in the asm file describing the function. */ static void -rl78_start_function (FILE *file, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED) +rl78_start_function (FILE *file) { int i; diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index c14cb92f0f32b..c9dddda1b4c30 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -148,6 +148,7 @@ UNSPEC_VMRGL_DIRECT UNSPEC_VSPLT_DIRECT UNSPEC_VMRGEW_DIRECT + UNSPEC_VMRGOW_DIRECT UNSPEC_VSUMSWS_DIRECT UNSPEC_VADDCUQ UNSPEC_VADDEUQM @@ -218,7 +219,7 @@ (define_mode_iterator VParity [V4SI V2DI V1TI - (TI "TARGET_VSX_TIMODE")]) + TI]) (define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")]) (define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")]) @@ -311,7 +312,7 @@ for (i = 0; i < num_elements; i++) RTVEC_ELT (v, i) = constm1_rtx; - emit_insn (gen_vec_initv4si (dest, gen_rtx_PARALLEL (mode, v))); + emit_insn (gen_vec_initv4sisi (dest, gen_rtx_PARALLEL (mode, v))); emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, dest, dest))); DONE; }) @@ -1357,15 +1358,24 @@ } [(set_attr "type" "vecperm")]) -(define_insn "p8_vmrgew_v4sf_direct" - [(set (match_operand:V4SF 0 "register_operand" "=v") - (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v") - (match_operand:V4SF 2 "register_operand" "v")] +(define_insn "p8_vmrgew__direct" + [(set (match_operand:VSX_W 0 "register_operand" "=v") + (unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v") + (match_operand:VSX_W 2 "register_operand" "v")] UNSPEC_VMRGEW_DIRECT))] "TARGET_P8_VECTOR" "vmrgew %0,%1,%2" [(set_attr "type" "vecperm")]) +(define_insn "p8_vmrgow__direct" + [(set (match_operand:VSX_W 0 "register_operand" "=v") + (unspec:VSX_W [(match_operand:VSX_W 1 "register_operand" "v") + (match_operand:VSX_W 2 "register_operand" "v")] + UNSPEC_VMRGOW_DIRECT))] + "TARGET_P8_VECTOR" + "vmrgow %0,%1,%2" + [(set_attr "type" "vecperm")]) + (define_expand "vec_widen_umult_even_v16qi" [(use (match_operand:V8HI 0 "register_operand" "")) (use (match_operand:V16QI 1 "register_operand" "")) @@ -2267,7 +2277,7 @@ RTVEC_ELT (v, 2) = GEN_INT (mask_val); RTVEC_ELT (v, 3) = GEN_INT (mask_val); - emit_insn (gen_vec_initv4si (mask, gen_rtx_PARALLEL (V4SImode, v))); + emit_insn (gen_vec_initv4sisi (mask, gen_rtx_PARALLEL (V4SImode, v))); emit_insn (gen_vector_select_v4sf (operands[0], operands[1], operands[2], gen_lowpart (V4SFmode, mask))); DONE; @@ -3409,7 +3419,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 0); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3445,7 +3455,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 6 : 17); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3481,7 +3491,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 8); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3517,7 +3527,7 @@ RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17); RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); DONE; }") @@ -3758,7 +3768,7 @@ = gen_rtx_CONST_INT (QImode, BYTES_BIG_ENDIAN ? 2 * i + 17 : 15 - 2 * i); } - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_altivec_vmulesb (even, operands[1], operands[2])); emit_insn (gen_altivec_vmulosb (odd, operands[1], operands[2])); emit_insn (gen_altivec_vperm_v8hiv16qi (operands[0], even, odd, mask)); @@ -3804,7 +3814,7 @@ RTVEC_ELT (v, i + j * size) = GEN_INT (i + (num_elements - 1 - j) * size); - emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v))); + emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); emit_insn (gen_altivec_vperm_ (operands[0], operands[1], operands[1], mask)); DONE; diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 71e35b709adf8..f119457ffe703 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -85,7 +85,7 @@ extern int dot_symbols; #undef RS6000_ABI_NAME #define RS6000_ABI_NAME "linux" -#define INVALID_64BIT "-m%s not supported in this configuration" +#define INVALID_64BIT "%<-m%s%> not supported in this configuration" #define INVALID_32BIT INVALID_64BIT #ifdef LINUX64_DEFAULT_ABI_ELFv2 diff --git a/gcc/config/rs6000/mm_malloc.h b/gcc/config/rs6000/mm_malloc.h new file mode 100644 index 0000000000000..a4115e6d78873 --- /dev/null +++ b/gcc/config/rs6000/mm_malloc.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2004-2017 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef _MM_MALLOC_H_INCLUDED +#define _MM_MALLOC_H_INCLUDED + +#include + +/* We can't depend on since the prototype of posix_memalign + may not be visible. */ +#ifndef __cplusplus +extern int posix_memalign (void **, size_t, size_t); +#else +extern "C" int posix_memalign (void **, size_t, size_t) throw (); +#endif + +static __inline void * +_mm_malloc (size_t size, size_t alignment) +{ + /* PowerPC64 ELF V2 ABI requires quadword alignment. */ + size_t vec_align = sizeof (__vector float); + /* Linux GLIBC malloc alignment is at least 2 X ptr size. */ + size_t malloc_align = (sizeof (void *) + sizeof (void *)); + void *ptr; + + if (alignment == malloc_align && alignment == vec_align) + return malloc (size); + if (alignment < vec_align) + alignment = vec_align; + if (posix_memalign (&ptr, alignment, size) == 0) + return ptr; + else + return NULL; +} + +static __inline void +_mm_free (void * ptr) +{ + free (ptr); +} + +#endif /* _MM_MALLOC_H_INCLUDED */ diff --git a/gcc/config/rs6000/paired.md b/gcc/config/rs6000/paired.md index c9f95867c0f5d..b0aa329d7b844 100644 --- a/gcc/config/rs6000/paired.md +++ b/gcc/config/rs6000/paired.md @@ -377,7 +377,7 @@ "ps_muls1 %0, %1, %2" [(set_attr "type" "fp")]) -(define_expand "vec_initv2sf" +(define_expand "vec_initv2sfsf" [(match_operand:V2SF 0 "gpc_reg_operand" "=f") (match_operand 1 "" "")] "TARGET_PAIRED_FLOAT" diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 466f9131aa047..63af03baa6fa4 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -827,7 +827,7 @@ (define_predicate "vsx_quad_dform_memory_operand" (match_code "mem") { - if (!TARGET_P9_DFORM_VECTOR || !MEM_P (op) || GET_MODE_SIZE (mode) != 16) + if (!TARGET_P9_VECTOR || !MEM_P (op) || GET_MODE_SIZE (mode) != 16) return false; return quad_address_p (XEXP (op, 0), mode, false); diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 7ffb3fd15b1e6..1c9a8db7c628b 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -430,8 +430,8 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags, rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7"); /* Note that the OPTION_MASK_DIRECT_MOVE flag is automatically turned on in the following condition: - 1. TARGET_P9_DFORM_SCALAR or TARGET_P9_DFORM_VECTOR are enabled - and OPTION_MASK_DIRECT_MOVE is not explicitly disabled. + 1. TARGET_P8_VECTOR is enabled and OPTION_MASK_DIRECT_MOVE is not + explicitly disabled. Hereafter, the OPTION_MASK_DIRECT_MOVE flag is considered to have been turned on explicitly. Note that the OPTION_MASK_DIRECT_MOVE flag is automatically @@ -545,8 +545,7 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags, also considered to have been turned off explicitly. Note that the OPTION_MASK_P9_VECTOR is automatically turned on in the following conditions: - 1. If TARGET_P9_DFORM_SCALAR or TARGET_P9_DFORM_VECTOR and - OPTION_MASK_P9_VECTOR was not turned off explicitly. + 1. If TARGET_P9_MINMAX was turned on explicitly. Hereafter, THE OPTION_MASK_P9_VECTOR flag is considered to have been turned on explicitly. */ if ((flags & OPTION_MASK_P9_VECTOR) != 0) @@ -5812,7 +5811,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, types. */ if (nargs != 2) { - error ("vec_mul only accepts 2 arguments"); + error ("builtin %qs only accepts 2 arguments", "vec_mul"); return error_mark_node; } @@ -5863,7 +5862,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, for it (prior to power 9). */ if (nargs != 2) { - error ("vec_cmpne only accepts 2 arguments"); + error ("builtin %qs only accepts 2 arguments", "vec_cmpne"); return error_mark_node; } @@ -5872,6 +5871,12 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, tree arg1 = (*arglist)[1]; tree arg1_type = TREE_TYPE (arg1); + /* Both arguments must be vectors and the types must be compatible. */ + if (TREE_CODE (arg0_type) != VECTOR_TYPE) + goto bad; + if (!lang_hooks.types_compatible_p (arg0_type, arg1_type)) + goto bad; + /* Power9 instructions provide the most efficient implementation of ALTIVEC_BUILTIN_VEC_CMPNE if the mode is not DImode or TImode or SFmode or DFmode. */ @@ -5881,12 +5886,6 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, || (TYPE_MODE (TREE_TYPE (arg0_type)) == SFmode) || (TYPE_MODE (TREE_TYPE (arg0_type)) == DFmode)) { - /* Both arguments must be vectors and the types must be compatible. */ - if (TREE_CODE (arg0_type) != VECTOR_TYPE) - goto bad; - if (!lang_hooks.types_compatible_p (arg0_type, arg1_type)) - goto bad; - switch (TYPE_MODE (TREE_TYPE (arg0_type))) { /* vec_cmpneq (va, vb) == vec_nor (vec_cmpeq (va, vb), @@ -5936,7 +5935,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, { const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDE ? "vec_adde": "vec_sube"; - error ("%s only accepts 3 arguments", name); + error ("builtin %qs only accepts 3 arguments", name); return error_mark_node; } @@ -5951,8 +5950,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, __int128) and the types must be compatible. */ if (TREE_CODE (arg0_type) != VECTOR_TYPE) goto bad; - if (!lang_hooks.types_compatible_p (arg0_type, arg1_type) || - !lang_hooks.types_compatible_p (arg1_type, arg2_type)) + if (!lang_hooks.types_compatible_p (arg0_type, arg1_type) + || !lang_hooks.types_compatible_p (arg1_type, arg2_type)) goto bad; switch (TYPE_MODE (TREE_TYPE (arg0_type))) @@ -6019,7 +6018,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, { const char *name = fcode == ALTIVEC_BUILTIN_VEC_ADDEC ? "vec_addec": "vec_subec"; - error ("%s only accepts 3 arguments", name); + error ("builtin %qs only accepts 3 arguments", name); return error_mark_node; } @@ -6034,8 +6033,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, __int128) and the types must be compatible. */ if (TREE_CODE (arg0_type) != VECTOR_TYPE) goto bad; - if (!lang_hooks.types_compatible_p (arg0_type, arg1_type) || - !lang_hooks.types_compatible_p (arg1_type, arg2_type)) + if (!lang_hooks.types_compatible_p (arg0_type, arg1_type) + || !lang_hooks.types_compatible_p (arg1_type, arg2_type)) goto bad; switch (TYPE_MODE (TREE_TYPE (arg0_type))) @@ -6126,19 +6125,14 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, vec *vec; const char *name = fcode == ALTIVEC_BUILTIN_VEC_SPLATS ? "vec_splats": "vec_promote"; - if (nargs == 0) - { - error ("%s only accepts %d arguments", name, (fcode == ALTIVEC_BUILTIN_VEC_PROMOTE)+1 ); - return error_mark_node; - } if (fcode == ALTIVEC_BUILTIN_VEC_SPLATS && nargs != 1) { - error ("%s only accepts 1 argument", name); + error ("builtin %qs only accepts 1 argument", name); return error_mark_node; } if (fcode == ALTIVEC_BUILTIN_VEC_PROMOTE && nargs != 2) { - error ("%s only accepts 2 arguments", name); + error ("builtin %qs only accepts 2 arguments", name); return error_mark_node; } /* Ignore promote's element argument. */ @@ -6204,7 +6198,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, /* No second argument. */ if (nargs != 2) { - error ("vec_extract only accepts 2 arguments"); + error ("builtin %qs only accepts 2 arguments", "vec_extract"); return error_mark_node; } @@ -6373,7 +6367,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, /* No second or third arguments. */ if (nargs != 3) { - error ("vec_insert only accepts 3 arguments"); + error ("builtin %qs only accepts 3 arguments", "vec_insert"); return error_mark_node; } @@ -6484,6 +6478,9 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, /* Strip qualifiers like "const" from the pointer arg. */ tree arg1_type = TREE_TYPE (arg1); + if (!POINTER_TYPE_P (arg1_type) && TREE_CODE (arg1_type) != ARRAY_TYPE) + goto bad; + tree inner_type = TREE_TYPE (arg1_type); if (TYPE_QUALS (TREE_TYPE (arg1_type)) != 0) { @@ -6572,11 +6569,6 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, arg2 = build1 (ADDR_EXPR, arg2_type, arg2_elt0); } - tree addr = fold_build2_loc (loc, POINTER_PLUS_EXPR, arg2_type, - arg2, arg1); - tree aligned = fold_build2_loc (loc, BIT_AND_EXPR, arg2_type, addr, - build_int_cst (arg2_type, -16)); - /* Find the built-in to make sure a compatible one exists; if not we fall back to default handling to get the error message. */ for (desc = altivec_overloaded_builtins; @@ -6589,6 +6581,12 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, && rs6000_builtin_type_compatible (TREE_TYPE (arg2), desc->op3)) { + tree addr = fold_build2_loc (loc, POINTER_PLUS_EXPR, arg2_type, + arg2, arg1); + tree aligned + = fold_build2_loc (loc, BIT_AND_EXPR, arg2_type, + addr, build_int_cst (arg2_type, -16)); + tree arg0_type = TREE_TYPE (arg0); if (TYPE_MODE (arg0_type) == V2DImode) /* Type-based aliasing analysis thinks vector long @@ -6694,7 +6692,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (nargs != 2) { - error ("__builtin_cmpb only accepts 2 arguments"); + error ("builtin %qs only accepts 2 arguments", "__builtin_cmpb"); return error_mark_node; } @@ -6714,8 +6712,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, overloaded_code = P6_BUILTIN_CMPB_32; } - while (desc->code && desc->code == fcode && - desc->overloaded_code != overloaded_code) + while (desc->code && desc->code == fcode + && desc->overloaded_code != overloaded_code) desc++; if (desc->code && (desc->code == fcode) @@ -6735,7 +6733,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (nargs != 2) { - error ("scalar_insert_exp only accepts 2 arguments"); + error ("builtin %qs only accepts 2 arguments", + "scalar_insert_exp"); return error_mark_node; } @@ -6761,8 +6760,8 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, else overloaded_code = P9V_BUILTIN_VSIEDP; } - while (desc->code && desc->code == fcode && - desc->overloaded_code != overloaded_code) + while (desc->code && desc->code == fcode + && desc->overloaded_code != overloaded_code) desc++; if (desc->code && (desc->code == fcode) && rs6000_builtin_type_compatible (types[0], desc->op1) @@ -6798,15 +6797,15 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (unsupported_builtin) { const char *name = rs6000_overloaded_builtin_name (fcode); - error ("Builtin function %s not supported in this compiler configuration", - name); + error ("builtin function %qs not supported in this compiler " + "configuration", name); return error_mark_node; } } bad: - { - const char *name = rs6000_overloaded_builtin_name (fcode); - error ("invalid parameter combination for AltiVec intrinsic %s", name); - return error_mark_node; - } + { + const char *name = rs6000_overloaded_builtin_name (fcode); + error ("invalid parameter combination for AltiVec intrinsic %qs", name); + return error_mark_node; + } } diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index 190f9123fa0ca..d4a8b94326a3b 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -38,8 +38,6 @@ /* For ISA 2.06, don't add ISEL, since in general it isn't a win, but altivec is a win so enable it. */ - /* OPTION_MASK_VSX_TIMODE should be set, but disable it for now until - PR 58587 is fixed. */ #define ISA_2_6_MASKS_EMBEDDED (ISA_2_5_MASKS_EMBEDDED | OPTION_MASK_POPCNTD) #define ISA_2_6_MASKS_SERVER (ISA_2_5_MASKS_SERVER \ | OPTION_MASK_POPCNTD \ @@ -63,8 +61,6 @@ | OPTION_MASK_ISEL \ | OPTION_MASK_MODULO \ | OPTION_MASK_P9_FUSION \ - | OPTION_MASK_P9_DFORM_SCALAR \ - | OPTION_MASK_P9_DFORM_VECTOR \ | OPTION_MASK_P9_MINMAX \ | OPTION_MASK_P9_MISC \ | OPTION_MASK_P9_VECTOR) @@ -78,8 +74,6 @@ /* Flags that need to be turned off if -mno-power9-vector. */ #define OTHER_P9_VECTOR_MASKS (OPTION_MASK_FLOAT128_HW \ - | OPTION_MASK_P9_DFORM_SCALAR \ - | OPTION_MASK_P9_DFORM_VECTOR \ | OPTION_MASK_P9_MINMAX) /* Flags that need to be turned off if -mno-power8-vector. */ @@ -93,8 +87,7 @@ | OPTION_MASK_EFFICIENT_UNALIGNED_VSX \ | OPTION_MASK_FLOAT128_KEYWORD \ | OPTION_MASK_FLOAT128_TYPE \ - | OPTION_MASK_P8_VECTOR \ - | OPTION_MASK_VSX_TIMODE) + | OPTION_MASK_P8_VECTOR) #define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC) @@ -130,8 +123,6 @@ | OPTION_MASK_NO_UPDATE \ | OPTION_MASK_P8_FUSION \ | OPTION_MASK_P8_VECTOR \ - | OPTION_MASK_P9_DFORM_SCALAR \ - | OPTION_MASK_P9_DFORM_VECTOR \ | OPTION_MASK_P9_FUSION \ | OPTION_MASK_P9_MINMAX \ | OPTION_MASK_P9_MISC \ @@ -147,8 +138,7 @@ | OPTION_MASK_SOFT_FLOAT \ | OPTION_MASK_STRICT_ALIGN_OPTIONAL \ | OPTION_MASK_TOC_FUSION \ - | OPTION_MASK_VSX \ - | OPTION_MASK_VSX_TIMODE) + | OPTION_MASK_VSX) #endif diff --git a/gcc/config/rs6000/rs6000-p8swap.c b/gcc/config/rs6000/rs6000-p8swap.c index 1557f7f587e21..7d2c97fab8af9 100644 --- a/gcc/config/rs6000/rs6000-p8swap.c +++ b/gcc/config/rs6000/rs6000-p8swap.c @@ -1431,9 +1431,10 @@ alignment_mask (rtx_insn *insn) } /* Given INSN that's a load or store based at BASE_REG, look for a - feeding computation that aligns its address on a 16-byte boundary. */ + feeding computation that aligns its address on a 16-byte boundary. + Return the rtx and its containing AND_INSN. */ static rtx -find_alignment_op (rtx_insn *insn, rtx base_reg) +find_alignment_op (rtx_insn *insn, rtx base_reg, rtx_insn **and_insn) { df_ref base_use; struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn); @@ -1454,8 +1455,8 @@ find_alignment_op (rtx_insn *insn, rtx base_reg) if (DF_REF_IS_ARTIFICIAL (base_def_link->ref)) break; - rtx_insn *and_insn = DF_REF_INSN (base_def_link->ref); - and_operation = alignment_mask (and_insn); + *and_insn = DF_REF_INSN (base_def_link->ref); + and_operation = alignment_mask (*and_insn); if (and_operation != 0) break; } @@ -1477,7 +1478,8 @@ recombine_lvx_pattern (rtx_insn *insn, del_info *to_delete) rtx mem = XEXP (SET_SRC (body), 0); rtx base_reg = XEXP (mem, 0); - rtx and_operation = find_alignment_op (insn, base_reg); + rtx_insn *and_insn; + rtx and_operation = find_alignment_op (insn, base_reg, &and_insn); if (and_operation != 0) { @@ -1501,7 +1503,21 @@ recombine_lvx_pattern (rtx_insn *insn, del_info *to_delete) to_delete[INSN_UID (swap_insn)].replace = true; to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn; - XEXP (mem, 0) = and_operation; + /* However, first we must be sure that we make the + base register from the AND operation available + in case the register has been overwritten. Copy + the base register to a new pseudo and use that + as the base register of the AND operation in + the new LVX instruction. */ + rtx and_base = XEXP (and_operation, 0); + rtx new_reg = gen_reg_rtx (GET_MODE (and_base)); + rtx copy = gen_rtx_SET (new_reg, and_base); + rtx_insn *new_insn = emit_insn_after (copy, and_insn); + set_block_for_insn (new_insn, BLOCK_FOR_INSN (and_insn)); + df_insn_rescan (new_insn); + + XEXP (mem, 0) = gen_rtx_AND (GET_MODE (and_base), new_reg, + XEXP (and_operation, 1)); SET_SRC (body) = mem; INSN_CODE (insn) = -1; /* Force re-recognition. */ df_insn_rescan (insn); @@ -1524,7 +1540,8 @@ recombine_stvx_pattern (rtx_insn *insn, del_info *to_delete) rtx mem = SET_DEST (body); rtx base_reg = XEXP (mem, 0); - rtx and_operation = find_alignment_op (insn, base_reg); + rtx_insn *and_insn; + rtx and_operation = find_alignment_op (insn, base_reg, &and_insn); if (and_operation != 0) { @@ -1552,7 +1569,21 @@ recombine_stvx_pattern (rtx_insn *insn, del_info *to_delete) to_delete[INSN_UID (swap_insn)].replace = true; to_delete[INSN_UID (swap_insn)].replace_insn = swap_insn; - XEXP (mem, 0) = and_operation; + /* However, first we must be sure that we make the + base register from the AND operation available + in case the register has been overwritten. Copy + the base register to a new pseudo and use that + as the base register of the AND operation in + the new STVX instruction. */ + rtx and_base = XEXP (and_operation, 0); + rtx new_reg = gen_reg_rtx (GET_MODE (and_base)); + rtx copy = gen_rtx_SET (new_reg, and_base); + rtx_insn *new_insn = emit_insn_after (copy, and_insn); + set_block_for_insn (new_insn, BLOCK_FOR_INSN (and_insn)); + df_insn_rescan (new_insn); + + XEXP (mem, 0) = gen_rtx_AND (GET_MODE (and_base), new_reg, + XEXP (and_operation, 1)); SET_SRC (body) = src_reg; INSN_CODE (insn) = -1; /* Force re-recognition. */ df_insn_rescan (insn); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a7d2e7eb4702f..9ff73ec4213b8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2056,7 +2056,7 @@ rs6000_hard_regno_mode_ok (int regno, machine_mode mode) && (VECTOR_MEM_VSX_P (mode) || FLOAT128_VECTOR_P (mode) || reg_addr[mode].scalar_in_vmx_p - || (TARGET_VSX_TIMODE && mode == TImode) + || mode == TImode || (TARGET_VADDUQM && mode == V1TImode))) { if (FP_REGNO_P (regno)) @@ -2926,8 +2926,7 @@ rs6000_setup_reg_addr_masks (void) && (rc == RELOAD_REG_GPR || ((msize == 8 || m2 == SFmode) && (rc == RELOAD_REG_FPR - || (rc == RELOAD_REG_VMX - && TARGET_P9_DFORM_SCALAR))))) + || (rc == RELOAD_REG_VMX && TARGET_P9_VECTOR))))) addr_mask |= RELOAD_REG_OFFSET; /* VSX registers can do REG+OFFSET addresssing if ISA 3.0 @@ -2935,9 +2934,9 @@ rs6000_setup_reg_addr_masks (void) only 12-bits. While GPRs can handle the full offset range, VSX registers can only handle the restricted range. */ else if ((addr_mask != 0) && !indexed_only_p - && msize == 16 && TARGET_P9_DFORM_VECTOR + && msize == 16 && TARGET_P9_VECTOR && (ALTIVEC_OR_VSX_VECTOR_MODE (m2) - || (m2 == TImode && TARGET_VSX_TIMODE))) + || (m2 == TImode && TARGET_VSX))) { addr_mask |= RELOAD_REG_OFFSET; if (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX) @@ -3128,21 +3127,21 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) /* DFmode, see if we want to use the VSX unit. Memory is handled differently, so don't set rs6000_vector_mem. */ - if (TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE) + if (TARGET_VSX) { rs6000_vector_unit[DFmode] = VECTOR_VSX; rs6000_vector_align[DFmode] = 64; } /* SFmode, see if we want to use the VSX unit. */ - if (TARGET_P8_VECTOR && TARGET_VSX_SCALAR_FLOAT) + if (TARGET_P8_VECTOR) { rs6000_vector_unit[SFmode] = VECTOR_VSX; rs6000_vector_align[SFmode] = 32; } /* Allow TImode in VSX register and set the VSX memory macros. */ - if (TARGET_VSX && TARGET_VSX_TIMODE) + if (TARGET_VSX) { rs6000_vector_mem[TImode] = VECTOR_VSX; rs6000_vector_align[TImode] = align64; @@ -3203,9 +3202,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS; /* DFmode */ rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS; /* DFmode */ rs6000_constraints[RS6000_CONSTRAINT_wi] = VSX_REGS; /* DImode */ - - if (TARGET_VSX_TIMODE) - rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS; /* TImode */ + rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS; /* TImode */ } /* Add conditional constraints based on various options, to allow us to @@ -3241,11 +3238,6 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS; rs6000_constraints[RS6000_CONSTRAINT_ww] = VSX_REGS; } - else if (TARGET_P8_VECTOR) - { - rs6000_constraints[RS6000_CONSTRAINT_wy] = FLOAT_REGS; - rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS; - } else if (TARGET_VSX) rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS; @@ -3262,13 +3254,14 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS; /* TFmode */ } - /* Support for new D-form instructions. */ - if (TARGET_P9_DFORM_SCALAR) - rs6000_constraints[RS6000_CONSTRAINT_wb] = ALTIVEC_REGS; - - /* Support for ISA 3.0 (power9) vectors. */ if (TARGET_P9_VECTOR) - rs6000_constraints[RS6000_CONSTRAINT_wo] = VSX_REGS; + { + /* Support for new D-form instructions. */ + rs6000_constraints[RS6000_CONSTRAINT_wb] = ALTIVEC_REGS; + + /* Support for ISA 3.0 (power9) vectors. */ + rs6000_constraints[RS6000_CONSTRAINT_wo] = VSX_REGS; + } /* Support for new direct moves (ISA 3.0 + 64bit). */ if (TARGET_DIRECT_MOVE_128) @@ -3332,7 +3325,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_di_load; } - if (TARGET_VSX_TIMODE) + if (TARGET_VSX) { reg_addr[TImode].reload_store = CODE_FOR_reload_ti_di_store; reg_addr[TImode].reload_load = CODE_FOR_reload_ti_di_load; @@ -3416,7 +3409,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) reg_addr[SDmode].reload_load = CODE_FOR_reload_sd_si_load; } - if (TARGET_VSX_TIMODE) + if (TARGET_VSX) { reg_addr[TImode].reload_store = CODE_FOR_reload_ti_si_store; reg_addr[TImode].reload_load = CODE_FOR_reload_ti_si_load; @@ -3549,7 +3542,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) reg_addr[xmode].fusion_addis_ld[rtype] = addis_insns[i].load; reg_addr[xmode].fusion_addis_st[rtype] = addis_insns[i].store; - if (rtype == RELOAD_REG_FPR && TARGET_P9_DFORM_SCALAR) + if (rtype == RELOAD_REG_FPR && TARGET_P9_VECTOR) { reg_addr[xmode].fusion_addis_ld[RELOAD_REG_VMX] = addis_insns[i].load; @@ -3648,11 +3641,14 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) if (rs6000_recip_control) { if (!flag_finite_math_only) - warning (0, "-mrecip requires -ffinite-math or -ffast-math"); + warning (0, "%qs requires %qs or %qs", "-mrecip", "-ffinite-math", + "-ffast-math"); if (flag_trapping_math) - warning (0, "-mrecip requires -fno-trapping-math or -ffast-math"); + warning (0, "%qs requires %qs or %qs", "-mrecip", + "-fno-trapping-math", "-ffast-math"); if (!flag_reciprocal_math) - warning (0, "-mrecip requires -freciprocal-math or -ffast-math"); + warning (0, "%qs requires %qs or %qs", "-mrecip", "-freciprocal-math", + "-ffast-math"); if (flag_finite_math_only && !flag_trapping_math && flag_reciprocal_math) { if (RS6000_RECIP_HAVE_RE_P (SFmode) @@ -3752,7 +3748,7 @@ darwin_rs6000_override_options (void) if (TARGET_64BIT && ! TARGET_POWERPC64) { rs6000_isa_flags |= OPTION_MASK_POWERPC64; - warning (0, "-m64 requires PowerPC64 architecture, enabling"); + warning (0, "%qs requires PowerPC64 architecture, enabling", "-m64"); } if (flag_mkernel) { @@ -3934,8 +3930,9 @@ rs6000_option_override_internal (bool global_init_p) && rs6000_alignment_flags == MASK_ALIGN_POWER && DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT) - warning (0, "-malign-power is not supported for 64-bit Darwin;" - " it is incompatible with the installed C and C++ libraries"); + warning (0, "%qs is not supported for 64-bit Darwin;" + " it is incompatible with the installed C and C++ libraries", + "-malign-power"); /* Numerous experiment shows that IRA based loop pressure calculation works better for RTL loop invariant motion on targets @@ -4153,14 +4150,16 @@ rs6000_option_override_internal (bool global_init_p) { rs6000_isa_flags &= ~OPTION_MASK_MULTIPLE; if ((rs6000_isa_flags_explicit & OPTION_MASK_MULTIPLE) != 0) - warning (0, "-mmultiple is not supported on little endian systems"); + warning (0, "%qs is not supported on little endian systems", + "-mmultiple"); } if (TARGET_STRING) { rs6000_isa_flags &= ~OPTION_MASK_STRING; if ((rs6000_isa_flags_explicit & OPTION_MASK_STRING) != 0) - warning (0, "-mstring is not supported on little endian systems"); + warning (0, "%qs is not supported on little endian systems", + "-mstring"); } } @@ -4182,6 +4181,10 @@ rs6000_option_override_internal (bool global_init_p) rs6000_altivec_element_order = 0; } + if (!rs6000_fold_gimple) + fprintf (stderr, + "gimple folding of rs6000 builtins has been disabled.\n"); + /* Add some warnings for VSX. */ if (TARGET_VSX) { @@ -4236,8 +4239,7 @@ rs6000_option_override_internal (bool global_init_p) /* For the newer switches (vsx, dfp, etc.) set some of the older options, unless the user explicitly used the -mno-