diff --git a/ChangeLog b/ChangeLog index 1965414b4710..96a4056e42c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2023-06-25 Lehua Ding + + * MAINTAINERS: Add Lehua Ding to write after approval + +2023-06-25 Iain Sandoe + + * Makefile.def: Pass the enable-host-pie value to GCC configure. + * Makefile.in: Regenerate. + * configure: Regenerate. + * configure.ac: Adjust the logic for shared and PIE host flags to + ensure that PIE is passed for hosts that require it. + 2023-06-16 YunQiang Su * MAINTAINERS (Write After Approval): move Matthew Fortune diff --git a/MAINTAINERS b/MAINTAINERS index 4825ee449aed..bac773ad0af0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -394,6 +394,7 @@ Chris Demetriou Sameera Deshpande Wilco Dijkstra Benoit Dupont de Dinechin +Lehua Ding Jason Eckhardt Bernd Edlinger Phil Edwards diff --git a/Makefile.def b/Makefile.def index 35e994eb77ef..9b4a8a2bf7ac 100644 --- a/Makefile.def +++ b/Makefile.def @@ -47,7 +47,8 @@ host_modules= { module= fixincludes; bootstrap=true; host_modules= { module= flex; no_check_cross= true; }; host_modules= { module= gas; bootstrap=true; }; host_modules= { module= gcc; bootstrap=true; - extra_make_flags="$(EXTRA_GCC_FLAGS)"; }; + extra_make_flags="$(EXTRA_GCC_FLAGS)"; + extra_configure_flags='@gcc_host_pie@'; }; host_modules= { module= gmp; lib_path=.libs; bootstrap=true; // Work around in-tree gmp configure bug with missing flex. extra_configure_flags='--disable-shared LEX="touch lex.yy.c" @host_libs_picflag@'; diff --git a/Makefile.in b/Makefile.in index b559454cc90b..45f09f9308f2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12021,7 +12021,7 @@ configure-gcc: $$s/$$module_srcdir/configure \ --srcdir=$${topdir}/$$module_srcdir \ $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ - --target=${target_alias} \ + --target=${target_alias} @gcc_host_pie@ \ || exit 1 @endif gcc @@ -12056,7 +12056,8 @@ configure-stage1-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ \ - $(STAGE1_CONFIGURE_FLAGS) + $(STAGE1_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stage2-gcc maybe-configure-stage2-gcc @@ -12089,7 +12090,8 @@ configure-stage2-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGE2_CONFIGURE_FLAGS) + $(STAGE2_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stage3-gcc maybe-configure-stage3-gcc @@ -12122,7 +12124,8 @@ configure-stage3-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGE3_CONFIGURE_FLAGS) + $(STAGE3_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stage4-gcc maybe-configure-stage4-gcc @@ -12155,7 +12158,8 @@ configure-stage4-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGE4_CONFIGURE_FLAGS) + $(STAGE4_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stageprofile-gcc maybe-configure-stageprofile-gcc @@ -12188,7 +12192,8 @@ configure-stageprofile-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGEprofile_CONFIGURE_FLAGS) + $(STAGEprofile_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stagetrain-gcc maybe-configure-stagetrain-gcc @@ -12221,7 +12226,8 @@ configure-stagetrain-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGEtrain_CONFIGURE_FLAGS) + $(STAGEtrain_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stagefeedback-gcc maybe-configure-stagefeedback-gcc @@ -12254,7 +12260,8 @@ configure-stagefeedback-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGEfeedback_CONFIGURE_FLAGS) + $(STAGEfeedback_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stageautoprofile-gcc maybe-configure-stageautoprofile-gcc @@ -12287,7 +12294,8 @@ configure-stageautoprofile-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGEautoprofile_CONFIGURE_FLAGS) + $(STAGEautoprofile_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap .PHONY: configure-stageautofeedback-gcc maybe-configure-stageautofeedback-gcc @@ -12320,7 +12328,8 @@ configure-stageautofeedback-gcc: $(HOST_CONFIGARGS) --build=${build_alias} --host=${host_alias} \ --target=${target_alias} \ --with-build-libsubdir=$(HOST_SUBDIR) \ - $(STAGEautofeedback_CONFIGURE_FLAGS) + $(STAGEautofeedback_CONFIGURE_FLAGS) \ + @gcc_host_pie@ @endif gcc-bootstrap diff --git a/c++tools/ChangeLog b/c++tools/ChangeLog index 5d98eef48603..7efb9fa828a1 100644 --- a/c++tools/ChangeLog +++ b/c++tools/ChangeLog @@ -1,3 +1,8 @@ +2023-06-22 Marek Polacek + + * configure.ac (--enable-host-bind-now): New check. + * configure: Regenerate. + 2023-06-15 Marek Polacek * Makefile.in: Rename PIEFLAG to PICFLAG. Set LD_PICFLAG. Use it. diff --git a/c++tools/configure b/c++tools/configure index 880870093839..006efe07b354 100755 --- a/c++tools/configure +++ b/c++tools/configure @@ -628,6 +628,7 @@ EGREP GREP CXXCPP LD_PICFLAG +enable_host_bind_now PICFLAG MAINTAINER CXX_AUX_TOOLS @@ -702,6 +703,7 @@ enable_maintainer_mode enable_checking enable_default_pie enable_host_pie +enable_host_bind_now with_gcc_major_version_only ' ac_precious_vars='build_alias @@ -1336,6 +1338,7 @@ Optional Features: yes,no,all,none,release. --enable-default-pie enable Position Independent Executable as default --enable-host-pie build host code as PIE + --enable-host-bind-now link host code as BIND_NOW Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -3007,6 +3010,14 @@ fi +# Enable --enable-host-bind-now +# Check whether --enable-host-bind-now was given. +if test "${enable_host_bind_now+set}" = set; then : + enableval=$enable_host_bind_now; LD_PICFLAG="$LD_PICFLAG -Wl,-z,now" +fi + + + # Check if O_CLOEXEC is defined by fcntl diff --git a/c++tools/configure.ac b/c++tools/configure.ac index 44dfaccbbfaf..c2a16601425c 100644 --- a/c++tools/configure.ac +++ b/c++tools/configure.ac @@ -110,6 +110,13 @@ AC_ARG_ENABLE(host-pie, [build host code as PIE])], [PICFLAG=-fPIE; LD_PICFLAG=-pie], []) AC_SUBST(PICFLAG) + +# Enable --enable-host-bind-now +AC_ARG_ENABLE(host-bind-now, +[AS_HELP_STRING([--enable-host-bind-now], + [link host code as BIND_NOW])], +[LD_PICFLAG="$LD_PICFLAG -Wl,-z,now"], []) +AC_SUBST(enable_host_bind_now) AC_SUBST(LD_PICFLAG) # Check if O_CLOEXEC is defined by fcntl diff --git a/configure b/configure index 57159126f3c3..0d3f5c6455d4 100755 --- a/configure +++ b/configure @@ -689,6 +689,7 @@ stage1_languages host_libs_picflag PICFLAG host_shared +gcc_host_pie host_pie extra_linker_plugin_flags extra_linker_plugin_configure_flags @@ -8649,23 +8650,31 @@ fi -# Enable --enable-host-pie. -# Checked early to determine whether jit is an 'all' language +# Handle --enable-host-pie +# If host PIE executables are the default (or must be forced on) for some host, +# we must pass that configuration to the gcc directory. +gcc_host_pie= # Check whether --enable-host-pie was given. if test "${enable_host_pie+set}" = set; then : enableval=$enable_host_pie; host_pie=$enableval case $host in - x86_64-*-darwin* | aarch64-*-darwin*) + *-*-darwin2*) if test x$host_pie != xyes ; then - # PIC is the default, and actually cannot be switched off. - echo configure.ac: warning: PIC code is required for the configured target, host-shared setting ignored. 1>&2 + # for Darwin20+ this is required. + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: PIE executables are required for the configured host, host-pie setting ignored." >&5 +$as_echo "$as_me: WARNING: PIE executables are required for the configured host, host-pie setting ignored." >&2;} host_pie=yes + gcc_host_pie=--enable-host-pie fi ;; *) ;; esac else case $host in - *-*-darwin2*) host_pie=yes ;; + *-*-darwin2*) + # Default to PIE (mandatory for aarch64). + host_pie=yes + gcc_host_pie=--enable-host-pie + ;; *) host_pie=no ;; esac fi @@ -8673,6 +8682,7 @@ fi + # Enable --enable-host-shared. # Checked early to determine whether jit is an 'all' language # Check whether --enable-host-shared was given. @@ -8682,21 +8692,24 @@ if test "${enable_host_shared+set}" = set; then : x86_64-*-darwin* | aarch64-*-darwin*) if test x$host_shared != xyes ; then # PIC is the default, and actually cannot be switched off. - echo configure.ac: warning: PIC code is required for the configured target, host-shared setting ignored. 1>&2 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: PIC code is required for the configured host; host-shared setting ignored." >&5 +$as_echo "$as_me: WARNING: PIC code is required for the configured host; host-shared setting ignored." >&2;} host_shared=yes fi ;; *-*-darwin*) - if test x$host_pie == xyes ; then - echo configure.ac: warning: PIC code is required for PIE executables. 1>&2 + if test x$host_pie = xyes -a x$host_shared != xyes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: PIC code is required for PIE host executables host-shared setting ignored." >&5 +$as_echo "$as_me: WARNING: PIC code is required for PIE host executables host-shared setting ignored." >&2;} host_shared=yes fi ;; *) ;; esac else case $host in + # 64B x86_64 and Aarch64 Darwin default to PIC. x86_64-*-darwin* | aarch64-*-darwin*) host_shared=yes ;; - # Darwin needs PIC objects to link PIE executables. - *-*-darwin*) host_shared=host_pie ;; + # 32B and powerpc64 Darwin must use PIC to link PIE exes. + *-*-darwin*) host_shared=$host_pie ;; *) host_shared=no;; esac fi @@ -8705,7 +8718,18 @@ fi if test x$host_shared = xyes; then - PICFLAG=-fPIC + case $host in + *-*-darwin*) + # Since host shared is the default for 64b Darwin, and also enabled for + # host_pie, ensure that we present the PIE flag when host_pie is active. + if test x$host_pie = xyes; then + PICFLAG=-fPIE + fi + ;; + *) + PICFLAG=-fPIC + ;; + esac elif test x$host_pie = xyes; then PICFLAG=-fPIE else diff --git a/configure.ac b/configure.ac index 11b68b7b614d..dddab2a56d86 100644 --- a/configure.ac +++ b/configure.ac @@ -1891,27 +1891,35 @@ AC_ARG_ENABLE(linker-plugin-flags, extra_linker_plugin_flags=) AC_SUBST(extra_linker_plugin_flags) -# Enable --enable-host-pie. -# Checked early to determine whether jit is an 'all' language +# Handle --enable-host-pie +# If host PIE executables are the default (or must be forced on) for some host, +# we must pass that configuration to the gcc directory. +gcc_host_pie= AC_ARG_ENABLE(host-pie, [AS_HELP_STRING([--enable-host-pie], [build position independent host executables])], [host_pie=$enableval case $host in - x86_64-*-darwin* | aarch64-*-darwin*) + *-*-darwin2*) if test x$host_pie != xyes ; then - # PIC is the default, and actually cannot be switched off. - echo configure.ac: warning: PIC code is required for the configured target, host-shared setting ignored. 1>&2 + # for Darwin20+ this is required. + AC_MSG_WARN([PIE executables are required for the configured host, host-pie setting ignored.]) host_pie=yes + gcc_host_pie=--enable-host-pie fi ;; *) ;; esac], [case $host in - *-*-darwin2*) host_pie=yes ;; + *-*-darwin2*) + # Default to PIE (mandatory for aarch64). + host_pie=yes + gcc_host_pie=--enable-host-pie + ;; *) host_pie=no ;; esac]) AC_SUBST(host_pie) +AC_SUBST(gcc_host_pie) # Enable --enable-host-shared. # Checked early to determine whether jit is an 'all' language @@ -1923,27 +1931,39 @@ AC_ARG_ENABLE(host-shared, x86_64-*-darwin* | aarch64-*-darwin*) if test x$host_shared != xyes ; then # PIC is the default, and actually cannot be switched off. - echo configure.ac: warning: PIC code is required for the configured target, host-shared setting ignored. 1>&2 + AC_MSG_WARN([PIC code is required for the configured host; host-shared setting ignored.]) host_shared=yes fi ;; *-*-darwin*) - if test x$host_pie == xyes ; then - echo configure.ac: warning: PIC code is required for PIE executables. 1>&2 + if test x$host_pie = xyes -a x$host_shared != xyes ; then + AC_MSG_WARN([PIC code is required for PIE host executables host-shared setting ignored.]) host_shared=yes fi ;; *) ;; esac], [case $host in + # 64B x86_64 and Aarch64 Darwin default to PIC. x86_64-*-darwin* | aarch64-*-darwin*) host_shared=yes ;; - # Darwin needs PIC objects to link PIE executables. - *-*-darwin*) host_shared=host_pie ;; + # 32B and powerpc64 Darwin must use PIC to link PIE exes. + *-*-darwin*) host_shared=$host_pie ;; *) host_shared=no;; esac]) AC_SUBST(host_shared) if test x$host_shared = xyes; then - PICFLAG=-fPIC + case $host in + *-*-darwin*) + # Since host shared is the default for 64b Darwin, and also enabled for + # host_pie, ensure that we present the PIE flag when host_pie is active. + if test x$host_pie = xyes; then + PICFLAG=-fPIE + fi + ;; + *) + PICFLAG=-fPIC + ;; + esac elif test x$host_pie = xyes; then PICFLAG=-fPIE else diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 9b73cddaacad..92af01dc9c04 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,9 @@ +2023-06-22 David Malcolm + + * unicode/gen-box-drawing-chars.py: New file. + * unicode/gen-combining-chars.py: New file. + * unicode/gen-printable-chars.py: New file. + 2023-06-17 Thiago Jung Bauermann * testsuite-management/validate_failures.py (IsInterestingResult): diff --git a/contrib/unicode/gen-box-drawing-chars.py b/contrib/unicode/gen-box-drawing-chars.py new file mode 100755 index 000000000000..9a55266ab843 --- /dev/null +++ b/contrib/unicode/gen-box-drawing-chars.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# Script to generate gcc/text-art/box-drawing-chars.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 +# . */ + +import unicodedata + +def get_box_drawing_char_name(up: bool, + down: bool, + left: bool, + right: bool) -> str: + if 0: + print(f'{locals()=}') + if up and down: + vertical = True + up = False + down = False + else: + vertical = False + + if left and right: + horizontal = True + left = False + right = False + else: + horizontal = False + + weights = [] + heavy = [] + light = [] + dirs = [] + for dir_name in ('up', 'down', 'vertical', 'left', 'right', 'horizontal'): + val = locals()[dir_name] + if val: + dirs.append(dir_name.upper()) + + if not dirs: + return 'SPACE' + + name = 'BOX DRAWINGS' + #print(f'{light=} {heavy=}') + + if 0: + print(dirs) + + def weights_frag(weight: str, dirs: list, prefix: bool): + """ + Generate a fragment where all directions share the same weight, e.g.: + 'HEAVY HORIZONTAL' + 'DOWN LIGHT' + 'LEFT DOWN HEAVY' + 'HEAVY DOWN AND RIGHT' + """ + assert len(dirs) >= 1 + assert len(dirs) <= 2 + if prefix: + return f' {weight} ' + (' AND '.join(dirs)) + else: + return ' ' + (' '.join(dirs)) + f' {weight}' + + assert(len(dirs) >= 1 and len(dirs) <= 2) + name += weights_frag('LIGHT', dirs, True) + + return name + +print('/* Generated by contrib/unicode/gen-box-drawing-chars.py. */') +print() +for i in range(16): + up = (i & 8) + down = (i & 4) + left = (i & 2) + right = (i & 1) + name = get_box_drawing_char_name(up, down, left, right) + if i < 15: + trailing_comma = ',' + else: + trailing_comma = ' ' + unichar = unicodedata.lookup(name) + print(f'0x{ord(unichar):04X}{trailing_comma} /* "{unichar}": U+{ord(unichar):04X}: {name} */') diff --git a/contrib/unicode/gen-combining-chars.py b/contrib/unicode/gen-combining-chars.py new file mode 100755 index 000000000000..fb5ef50ba4ca --- /dev/null +++ b/contrib/unicode/gen-combining-chars.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# +# Script to generate libcpp/combining-chars.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 +# . */ + +from pprint import pprint +import unicodedata + +def is_combining_char(code_point) -> bool: + return unicodedata.combining(chr(code_point)) != 0 + +class Range: + def __init__(self, start, end, value): + self.start = start + self.end = end + self.value = value + + def __repr__(self): + return f'Range({self.start:x}, {self.end:x}, {self.value})' + +def make_ranges(value_callback): + ranges = [] + for code_point in range(0x10FFFF): + value = is_combining_char(code_point) + if 0: + print(f'{code_point=:x} {value=}') + if ranges and ranges[-1].value == value: + # Extend current range + ranges[-1].end = code_point + else: + # Start a new range + ranges.append(Range(code_point, code_point, value)) + return ranges + +ranges = make_ranges(is_combining_char) +if 0: + pprint(ranges) + +print(f"/* Generated by contrib/unicode/gen-combining-chars.py") +print(f" using version {unicodedata.unidata_version}" + " of the Unicode standard. */") +print("\nstatic const cppchar_t combining_range_ends[] = {", end="") +for i, r in enumerate(ranges): + if i % 8: + print(" ", end="") + else: + print("\n ", end="") + print("0x%x," % r.end, end="") +print("\n};\n") +print("static const bool is_combining[] = {", end="") +for i, r in enumerate(ranges): + if i % 24: + print(" ", end="") + else: + print("\n ", end="") + if r.value: + print("1,", end="") + else: + print("0,", end="") +print("\n};") diff --git a/contrib/unicode/gen-printable-chars.py b/contrib/unicode/gen-printable-chars.py new file mode 100755 index 000000000000..7684c086638b --- /dev/null +++ b/contrib/unicode/gen-printable-chars.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# +# Script to generate libcpp/printable-chars.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 +# . */ + +from pprint import pprint +import unicodedata + +def is_printable_char(code_point) -> bool: + category = unicodedata.category(chr(code_point)) + # "Cc" is "control" and "Cf" is "format" + return category[0] != 'C' + +class Range: + def __init__(self, start, end, value): + self.start = start + self.end = end + self.value = value + + def __repr__(self): + return f'Range({self.start:x}, {self.end:x}, {self.value})' + +def make_ranges(value_callback): + ranges = [] + for code_point in range(0x10FFFF): + value = is_printable_char(code_point) + if 0: + print(f'{code_point=:x} {value=}') + if ranges and ranges[-1].value == value: + # Extend current range + ranges[-1].end = code_point + else: + # Start a new range + ranges.append(Range(code_point, code_point, value)) + return ranges + +ranges = make_ranges(is_printable_char) +if 0: + pprint(ranges) + +print(f"/* Generated by contrib/unicode/gen-printable-chars.py") +print(f" using version {unicodedata.unidata_version}" + " of the Unicode standard. */") +print("\nstatic const cppchar_t printable_range_ends[] = {", end="") +for i, r in enumerate(ranges): + if i % 8: + print(" ", end="") + else: + print("\n ", end="") + print("0x%x," % r.end, end="") +print("\n};\n") +print("static const bool is_printable[] = {", end="") +for i, r in enumerate(ranges): + if i % 24: + print(" ", end="") + else: + print("\n ", end="") + if r.value: + print("1,", end="") + else: + print("0,", end="") +print("\n};") diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d9e42568ae5..a7d51b5038aa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,646 @@ +2023-06-25 Juzhe-Zhong + + * config/riscv/riscv-vsetvl.cc (vector_insn_info::parse_insn): Ehance + AVL propagation. + * config/riscv/riscv-vsetvl.h: New function. + +2023-06-25 Li Xu + + * config/riscv/riscv-vector-builtins-bases.cc: change emit_insn to + emit_move_insn + +2023-06-25 Juzhe-Zhong + + * config/riscv/autovec.md (len_load_): Remove. + (len_maskload): Remove. + (len_store_): New pattern. + (len_maskstore): New pattern. + * config/riscv/predicates.md (autovec_length_operand): New predicate. + * config/riscv/riscv-protos.h (enum insn_type): New enum. + (expand_load_store): New function. + * config/riscv/riscv-v.cc (emit_vlmax_masked_insn): Ditto. + (emit_nonvlmax_masked_insn): Ditto. + (expand_load_store): Ditto. + * config/riscv/riscv-vector-builtins.cc + (function_expander::use_contiguous_store_insn): Add avl_type operand + into pred_store. + * config/riscv/vector.md: Ditto. + +2023-06-25 Ju-Zhe Zhong + + * internal-fn.cc (expand_partial_store_optab_fn): Fix bug of BIAS + argument index. + +2023-06-25 Pan Li + + * config/riscv/vector.md: Revert. + +2023-06-25 Pan Li + + * config/riscv/genrvv-type-indexer.cc (valid_type): Revert changes. + * config/riscv/riscv-modes.def (RVV_TUPLE_MODES): Ditto. + (ADJUST_ALIGNMENT): Ditto. + (RVV_TUPLE_PARTIAL_MODES): Ditto. + (ADJUST_NUNITS): Ditto. + * config/riscv/riscv-vector-builtins-types.def (vfloat16mf4x2_t): Ditto. + (vfloat16mf4x3_t): Ditto. + (vfloat16mf4x4_t): Ditto. + (vfloat16mf4x5_t): Ditto. + (vfloat16mf4x6_t): Ditto. + (vfloat16mf4x7_t): Ditto. + (vfloat16mf4x8_t): Ditto. + (vfloat16mf2x2_t): Ditto. + (vfloat16mf2x3_t): Ditto. + (vfloat16mf2x4_t): Ditto. + (vfloat16mf2x5_t): Ditto. + (vfloat16mf2x6_t): Ditto. + (vfloat16mf2x7_t): Ditto. + (vfloat16mf2x8_t): Ditto. + (vfloat16m1x2_t): Ditto. + (vfloat16m1x3_t): Ditto. + (vfloat16m1x4_t): Ditto. + (vfloat16m1x5_t): Ditto. + (vfloat16m1x6_t): Ditto. + (vfloat16m1x7_t): Ditto. + (vfloat16m1x8_t): Ditto. + (vfloat16m2x2_t): Ditto. + (vfloat16m2x3_t): Diito. + (vfloat16m2x4_t): Diito. + (vfloat16m4x2_t): Diito. + * config/riscv/riscv-vector-builtins.def (vfloat16mf4x2_t): Ditto. + (vfloat16mf4x3_t): Ditto. + (vfloat16mf4x4_t): Ditto. + (vfloat16mf4x5_t): Ditto. + (vfloat16mf4x6_t): Ditto. + (vfloat16mf4x7_t): Ditto. + (vfloat16mf4x8_t): Ditto. + (vfloat16mf2x2_t): Ditto. + (vfloat16mf2x3_t): Ditto. + (vfloat16mf2x4_t): Ditto. + (vfloat16mf2x5_t): Ditto. + (vfloat16mf2x6_t): Ditto. + (vfloat16mf2x7_t): Ditto. + (vfloat16mf2x8_t): Ditto. + (vfloat16m1x2_t): Ditto. + (vfloat16m1x3_t): Ditto. + (vfloat16m1x4_t): Ditto. + (vfloat16m1x5_t): Ditto. + (vfloat16m1x6_t): Ditto. + (vfloat16m1x7_t): Ditto. + (vfloat16m1x8_t): Ditto. + (vfloat16m2x2_t): Ditto. + (vfloat16m2x3_t): Ditto. + (vfloat16m2x4_t): Ditto. + (vfloat16m4x2_t): Ditto. + * config/riscv/riscv-vector-switch.def (TUPLE_ENTRY): Ditto. + * config/riscv/riscv.md: Ditto. + * config/riscv/vector-iterators.md: Ditto. + +2023-06-25 Ju-Zhe Zhong + + * gimple-fold.cc (arith_overflowed_p): Apply LEN_MASK_{LOAD,STORE}. + (gimple_fold_partial_load_store_mem_ref): Ditto. + (gimple_fold_partial_store): Ditto. + (gimple_fold_call): Ditto. + +2023-06-25 liuhongt + + PR target/110309 + * config/i386/sse.md (maskload): + Refine pattern with UNSPEC_MASKLOAD. + (maskload): Ditto. + (*_load_mask): Extend mode iterator to + VI12HFBF_AVX512VL. + (*_load): Ditto. + +2023-06-25 Ju-Zhe Zhong + + * tree-ssa-alias.cc (call_may_clobber_ref_p_1): Add LEN_MASK_STORE. + +2023-06-25 Ju-Zhe Zhong + + * tree-ssa-alias.cc (ref_maybe_used_by_call_p_1): Apply + LEN_MASK_{LOAD,STORE} + +2023-06-25 yulong + + * config/riscv/vector.md: Add float16 attr at sew、vlmul and ratio. + +2023-06-24 Roger Sayle + + * config/i386/i386.md (*qi_ext_3): New define_insn. + +2023-06-24 Juzhe-Zhong + + * config/riscv/autovec.md (*fma): set clobber to Pmode in expand stage. + (*fma): Ditto. + (*fnma): Ditto. + (*fnma): Ditto. + +2023-06-24 Juzhe-Zhong + + * config/riscv/autovec.md (fma4): New pattern. + (*fma): Ditto. + (fnma4): Ditto. + (*fnma): Ditto. + (fms4): Ditto. + (*fms): Ditto. + (fnms4): Ditto. + (*fnms): Ditto. + * config/riscv/riscv-protos.h (emit_vlmax_fp_ternary_insn): + New function. + * config/riscv/riscv-v.cc (emit_vlmax_fp_ternary_insn): Ditto. + * config/riscv/vector.md: Fix attribute bug. + +2023-06-24 Ju-Zhe Zhong + + * tree-ssa-loop-ivopts.cc (get_mem_type_for_internal_fn): + Apply LEN_MASK_{LOAD,STORE}. + +2023-06-24 Ju-Zhe Zhong + + * tree-ssa-loop-ivopts.cc (get_alias_ptr_type_for_ptr_address): + Add LEN_MASK_{LOAD,STORE}. + +2023-06-24 David Malcolm + + * diagnostic-format-sarif.cc: Add #define INCLUDE_VECTOR. + * diagnostic.cc: Likewise. + * text-art/box-drawing.cc: Likewise. + * text-art/canvas.cc: Likewise. + * text-art/ruler.cc: Likewise. + * text-art/selftests.cc: Likewise. + * text-art/selftests.h (text_art::canvas): New forward decl. + * text-art/style.cc: Add #define INCLUDE_VECTOR. + * text-art/styled-string.cc: Likewise. + * text-art/table.cc: Likewise. + * text-art/table.h: Remove #include . + * text-art/theme.cc: Add #define INCLUDE_VECTOR. + * text-art/types.h: Check that INCLUDE_VECTOR is defined. + Remove #include of and . + * text-art/widget.cc: Add #define INCLUDE_VECTOR. + * text-art/widget.h: Remove #include . + +2023-06-24 Ju-Zhe Zhong + + * internal-fn.cc (expand_partial_store_optab_fn): Adapt for LEN_MASK_STORE. + (internal_load_fn_p): Add LEN_MASK_LOAD. + (internal_store_fn_p): Add LEN_MASK_STORE. + (internal_fn_mask_index): Add LEN_MASK_{LOAD,STORE}. + (internal_fn_stored_value_index): Add LEN_MASK_STORE. + (internal_len_load_store_bias): Add LEN_MASK_{LOAD,STORE}. + * optabs-tree.cc (can_vec_mask_load_store_p): Adapt for LEN_MASK_{LOAD,STORE}. + (get_len_load_store_mode): Ditto. + * optabs-tree.h (can_vec_mask_load_store_p): Ditto. + (get_len_load_store_mode): Ditto. + * tree-vect-stmts.cc (check_load_store_for_partial_vectors): Ditto. + (get_all_ones_mask): New function. + (vectorizable_store): Apply LEN_MASK_{LOAD,STORE} into vectorizer. + (vectorizable_load): Ditto. + +2023-06-23 Marek Polacek + + * doc/cpp.texi (__cplusplus): Document value for -std=c++26 and + -std=gnu++26. Document that for C++23, its value is 202302L. + * doc/invoke.texi: Document -std=c++26 and -std=gnu++26. + * dwarf2out.cc (highest_c_language): Handle GNU C++26. + (gen_compile_unit_die): Likewise. + +2023-06-23 Jan Hubicka + + * tree-ssa-phiprop.cc (propagate_with_phi): Compute post dominators on + demand. + (pass_phiprop::execute): Do not compute it here; return + update_ssa_only_virtuals if something changed. + (pass_data_phiprop): Remove TODO_update_ssa from todos. + +2023-06-23 Michael Meissner + Aaron Sawdey + + PR target/105325 + * config/rs6000/genfusion.pl (gen_ld_cmpi_p10_one): Fix problems that + allowed prefixed lwa to be generated. + * config/rs6000/fusion.md: Regenerate. + * config/rs6000/predicates.md (ds_form_mem_operand): Delete. + * config/rs6000/rs6000.md (prefixed attribute): Add support for load + plus compare immediate fused insns. + (maybe_prefixed): Likewise. + +2023-06-23 Roger Sayle + + * simplify-rtx.cc (simplify_subreg): Optimize lowpart SUBREGs + of ASHIFT to const0_rtx with sufficiently large shift count. + Optimize highpart SUBREGs of ASHIFT as the shift operand when + the shift count is the correct offset. Optimize SUBREGs of + multi-word logic operations if the SUBREGs of both operands + can be simplified. + +2023-06-23 Richard Biener + + * varasm.cc (initializer_constant_valid_p_1): Only + allow conversions between scalar floating point types. + +2023-06-23 Richard Biener + + * tree-vect-stmts.cc (vectorizable_assignment): + Properly handle non-integral operands when analyzing + conversions. + +2023-06-23 Prathamesh Kulkarni + + PR tree-optimization/110280 + * match.pd (vec_perm_expr(v, v, mask) -> v): Explicitly build vector + using build_vector_from_val with the element of input operand, and + mask's type if operand and mask's types don't match. + +2023-06-23 Richard Biener + + * fold-const.cc (tree_simple_nonnegative_warnv_p): Guard + the truth_value_p case with !VECTOR_TYPE_P. + +2023-06-23 Richard Biener + + * tree-vect-patterns.cc (vect_look_through_possible_promotion): + Exit early when the type isn't scalar integral. + +2023-06-23 Richard Biener + + * match.pd ((outertype)((innertype0)a+(innertype1)b) + -> ((newtype)a+(newtype)b)): Use element_precision + where appropriate. + +2023-06-23 Richard Biener + + * fold-const.cc (fold_binary_loc): Use element_precision + when trying (double)float1 CMP (double)float2 to + float1 CMP float2 simplification. + * match.pd: Likewise. + +2023-06-23 Richard Biener + + * tree-vect-stmts.cc (vectorizable_load): Avoid useless + copies of VMAT_INVARIANT vectorized stmts, fix SLP support. + +2023-06-23 Richard Biener + + * tree-vect-stmts.cc (vector_vector_composition_type): + Handle composition of a vector from a number of elements that + happens to match its number of lanes. + +2023-06-22 Marek Polacek + + * configure.ac (--enable-host-bind-now): New check. Add + -Wl,-z,now to LD_PICFLAG if --enable-host-bind-now. + * configure: Regenerate. + * doc/install.texi: Document --enable-host-bind-now. + +2023-06-22 Di Zhao OS + + * config/aarch64/aarch64.cc: Change fma_reassoc_width for ampere1. + +2023-06-22 Richard Biener + + PR tree-optimization/110332 + * tree-ssa-phiprop.cc (propagate_with_phi): Always + check aliasing with edge inserted loads. + +2023-06-22 Roger Sayle + Uros Bizjak + + * config/i386/i386-expand.cc (ix86_expand_sse_ptest): Recognize + expansion of ptestc with equal operands as producing const1_rtx. + * config/i386/i386.cc (ix86_rtx_costs): Provide accurate cost + estimates of UNSPEC_PTEST, where the ptest performs the PAND + or PAND of its operands. + * config/i386/sse.md (define_split): Transform CCCmode UNSPEC_PTEST + of reg_equal_p operands into an x86_stc instruction. + (define_split): Split pandn/ptestz/set{n?}e into ptestc/set{n?}c. + (define_split): Similar to above for strict_low_part destinations. + (define_split): Split pandn/ptestz/j{n?}e into ptestc/j{n?}c. + +2023-06-22 David Malcolm + + PR analyzer/106626 + * Makefile.in (ANALYZER_OBJS): Add analyzer/access-diagram.o. + * doc/invoke.texi (Wanalyzer-out-of-bounds): Add description of + text art. + (fanalyzer-debug-text-art): New. + +2023-06-22 David Malcolm + + * Makefile.in (OBJS-libcommon): Add text-art/box-drawing.o, + text-art/canvas.o, text-art/ruler.o, text-art/selftests.o, + text-art/style.o, text-art/styled-string.o, text-art/table.o, + text-art/theme.o, and text-art/widget.o. + * color-macros.h (COLOR_FG_BRIGHT_BLACK): New. + (COLOR_FG_BRIGHT_RED): New. + (COLOR_FG_BRIGHT_GREEN): New. + (COLOR_FG_BRIGHT_YELLOW): New. + (COLOR_FG_BRIGHT_BLUE): New. + (COLOR_FG_BRIGHT_MAGENTA): New. + (COLOR_FG_BRIGHT_CYAN): New. + (COLOR_FG_BRIGHT_WHITE): New. + (COLOR_BG_BRIGHT_BLACK): New. + (COLOR_BG_BRIGHT_RED): New. + (COLOR_BG_BRIGHT_GREEN): New. + (COLOR_BG_BRIGHT_YELLOW): New. + (COLOR_BG_BRIGHT_BLUE): New. + (COLOR_BG_BRIGHT_MAGENTA): New. + (COLOR_BG_BRIGHT_CYAN): New. + (COLOR_BG_BRIGHT_WHITE): New. + * common.opt (fdiagnostics-text-art-charset=): New option. + (diagnostic-text-art.h): New SourceInclude. + (diagnostic_text_art_charset) New Enum and EnumValues. + * configure: Regenerate. + * configure.ac (gccdepdir): Add text-art to loop. + * diagnostic-diagram.h: New file. + * diagnostic-format-json.cc (json_emit_diagram): New. + (diagnostic_output_format_init_json): Wire it up to + context->m_diagrams.m_emission_cb. + * diagnostic-format-sarif.cc: Include "diagnostic-diagram.h" and + "text-art/canvas.h". + (sarif_result::on_nested_diagnostic): Move code to... + (sarif_result::add_related_location): ...this new function. + (sarif_result::on_diagram): New. + (sarif_builder::emit_diagram): New. + (sarif_builder::make_message_object_for_diagram): New. + (sarif_emit_diagram): New. + (diagnostic_output_format_init_sarif): Set + context->m_diagrams.m_emission_cb to sarif_emit_diagram. + * diagnostic-text-art.h: New file. + * diagnostic.cc: Include "diagnostic-text-art.h", + "diagnostic-diagram.h", and "text-art/theme.h". + (diagnostic_initialize): Initialize context->m_diagrams and + call diagnostics_text_art_charset_init. + (diagnostic_finish): Clean up context->m_diagrams.m_theme. + (diagnostic_emit_diagram): New. + (diagnostics_text_art_charset_init): New. + * diagnostic.h (text_art::theme): New forward decl. + (class diagnostic_diagram): Likewise. + (diagnostic_context::m_diagrams): New field. + (diagnostic_emit_diagram): New decl. + * doc/invoke.texi (Diagnostic Message Formatting Options): Add + -fdiagnostics-text-art-charset=. + (-fdiagnostics-plain-output): Add + -fdiagnostics-text-art-charset=none. + * gcc.cc: Include "diagnostic-text-art.h". + (driver_handle_option): Handle OPT_fdiagnostics_text_art_charset_. + * opts-common.cc (decode_cmdline_options_to_array): Add + "-fdiagnostics-text-art-charset=none" to expanded_args for + -fdiagnostics-plain-output. + * opts.cc: Include "diagnostic-text-art.h". + (common_handle_option): Handle OPT_fdiagnostics_text_art_charset_. + * pretty-print.cc (pp_unicode_character): New. + * pretty-print.h (pp_unicode_character): New decl. + * selftest-run-tests.cc: Include "text-art/selftests.h". + (selftest::run_tests): Call text_art_tests. + * text-art/box-drawing-chars.inc: New file, generated by + contrib/unicode/gen-box-drawing-chars.py. + * text-art/box-drawing.cc: New file. + * text-art/box-drawing.h: New file. + * text-art/canvas.cc: New file. + * text-art/canvas.h: New file. + * text-art/ruler.cc: New file. + * text-art/ruler.h: New file. + * text-art/selftests.cc: New file. + * text-art/selftests.h: New file. + * text-art/style.cc: New file. + * text-art/styled-string.cc: New file. + * text-art/table.cc: New file. + * text-art/table.h: New file. + * text-art/theme.cc: New file. + * text-art/theme.h: New file. + * text-art/types.h: New file. + * text-art/widget.cc: New file. + * text-art/widget.h: New file. + +2023-06-21 Uros Bizjak + + * function.h (emit_initial_value_sets): + Change return type from int to void. + (aggregate_value_p): Change return type from int to bool. + (prologue_contains): Ditto. + (epilogue_contains): Ditto. + (prologue_epilogue_contains): Ditto. + * function.cc (temp_slot): Make "in_use" variable bool. + (make_slot_available): Update for changed "in_use" variable. + (assign_stack_temp_for_type): Ditto. + (emit_initial_value_sets): Change return type from int to void + and update function body accordingly. + (instantiate_virtual_regs): Ditto. + (rest_of_handle_thread_prologue_and_epilogue): Ditto. + (safe_insn_predicate): Change return type from int to bool. + (aggregate_value_p): Change return type from int to bool + and update function body accordingly. + (prologue_contains): Change return type from int to bool. + (prologue_epilogue_contains): Ditto. + +2023-06-21 Alexander Monakov + + * common.opt (fp_contract_mode) [on]: Remove fallback. + * config/sh/sh.md (*fmasf4): Correct flag_fp_contract_mode test. + * doc/invoke.texi (-ffp-contract): Update. + * trans-mem.cc (diagnose_tm_1): Skip internal function calls. + +2023-06-21 Kyrylo Tkachov + + * config/aarch64/aarch64-sve.md (mask_gather_load): + Add alternatives to prefer to avoid same input and output Z register. + (mask_gather_load): Likewise. + (*mask_gather_load_xtw_unpacked): Likewise. + (*mask_gather_load_sxtw): Likewise. + (*mask_gather_load_uxtw): Likewise. + (@aarch64_gather_load_): + Likewise. + (@aarch64_gather_load_): + Likewise. + (*aarch64_gather_load_ + _xtw_unpacked): Likewise. + (*aarch64_gather_load_ + _sxtw): Likewise. + (*aarch64_gather_load_ + _uxtw): Likewise. + (@aarch64_ldff1_gather): Likewise. + (@aarch64_ldff1_gather): Likewise. + (*aarch64_ldff1_gather_sxtw): Likewise. + (*aarch64_ldff1_gather_uxtw): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (*aarch64_ldff1_gather_ + _sxtw): Likewise. + (*aarch64_ldff1_gather_ + _uxtw): Likewise. + * config/aarch64/aarch64-sve2.md (@aarch64_gather_ldnt): Likewise. + (@aarch64_gather_ldnt_ + ): Likewise. + +2023-06-21 Kyrylo Tkachov + + * config/aarch64/aarch64-sve.md (mask_gather_load): + Convert to compact alternatives syntax. + (mask_gather_load): Likewise. + (*mask_gather_load_xtw_unpacked): Likewise. + (*mask_gather_load_sxtw): Likewise. + (*mask_gather_load_uxtw): Likewise. + (@aarch64_gather_load_): + Likewise. + (@aarch64_gather_load_): + Likewise. + (*aarch64_gather_load_ + _xtw_unpacked): Likewise. + (*aarch64_gather_load_ + _sxtw): Likewise. + (*aarch64_gather_load_ + _uxtw): Likewise. + (@aarch64_ldff1_gather): Likewise. + (@aarch64_ldff1_gather): Likewise. + (*aarch64_ldff1_gather_sxtw): Likewise. + (*aarch64_ldff1_gather_uxtw): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (*aarch64_ldff1_gather_ + _sxtw): Likewise. + (*aarch64_ldff1_gather_ + _uxtw): Likewise. + * config/aarch64/aarch64-sve2.md (@aarch64_gather_ldnt): Likewise. + (@aarch64_gather_ldnt_ + ): Likewise. + +2023-06-21 Kyrylo Tkachov + + Revert: + 2023-06-21 Kyrylo Tkachov + + * config/aarch64/aarch64-sve.md (mask_gather_load): + Convert to compact alternatives syntax. + (mask_gather_load): Likewise. + (*mask_gather_load_xtw_unpacked): Likewise. + (*mask_gather_load_sxtw): Likewise. + (*mask_gather_load_uxtw): Likewise. + (@aarch64_gather_load_): + Likewise. + (@aarch64_gather_load_): + Likewise. + (*aarch64_gather_load_ + _xtw_unpacked): Likewise. + (*aarch64_gather_load_ + _sxtw): Likewise. + (*aarch64_gather_load_ + _uxtw): Likewise. + (@aarch64_ldff1_gather): Likewise. + (@aarch64_ldff1_gather): Likewise. + (*aarch64_ldff1_gather_sxtw): Likewise. + (*aarch64_ldff1_gather_uxtw): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (*aarch64_ldff1_gather_ + _sxtw): Likewise. + (*aarch64_ldff1_gather_ + _uxtw): Likewise. + * config/aarch64/aarch64-sve2.md (@aarch64_gather_ldnt): Likewise. + (@aarch64_gather_ldnt_ + ): Likewise. + +2023-06-21 Ju-Zhe Zhong + + * optabs-query.cc (can_vec_mask_load_store_p): Move to optabs-tree.cc. + (get_len_load_store_mode): Ditto. + * optabs-query.h (can_vec_mask_load_store_p): Move to optabs-tree.h. + (get_len_load_store_mode): Ditto. + * optabs-tree.cc (can_vec_mask_load_store_p): New function. + (get_len_load_store_mode): Ditto. + * optabs-tree.h (can_vec_mask_load_store_p): Ditto. + (get_len_load_store_mode): Ditto. + * tree-if-conv.cc: include optabs-tree instead of optabs-query + +2023-06-21 Richard Biener + + * tree-ssa-loop-ivopts.cc (add_iv_candidate_for_use): Use + split_constant_offset for the POINTER_PLUS_EXPR case. + +2023-06-21 Richard Biener + + * tree-ssa-loop-ivopts.cc (record_group_use): Use + split_constant_offset. + +2023-06-21 Richard Biener + + * tree-loop-distribution.cc (classify_builtin_st): Use + split_constant_offset. + * tree-ssa-loop-ivopts.h (strip_offset): Remove. + * tree-ssa-loop-ivopts.cc (strip_offset): Make static. + +2023-06-21 Kyrylo Tkachov + + * config/aarch64/aarch64-sve.md (mask_gather_load): + Convert to compact alternatives syntax. + (mask_gather_load): Likewise. + (*mask_gather_load_xtw_unpacked): Likewise. + (*mask_gather_load_sxtw): Likewise. + (*mask_gather_load_uxtw): Likewise. + (@aarch64_gather_load_): + Likewise. + (@aarch64_gather_load_): + Likewise. + (*aarch64_gather_load_ + _xtw_unpacked): Likewise. + (*aarch64_gather_load_ + _sxtw): Likewise. + (*aarch64_gather_load_ + _uxtw): Likewise. + (@aarch64_ldff1_gather): Likewise. + (@aarch64_ldff1_gather): Likewise. + (*aarch64_ldff1_gather_sxtw): Likewise. + (*aarch64_ldff1_gather_uxtw): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (@aarch64_ldff1_gather_ + ): Likewise. + (*aarch64_ldff1_gather_ + _sxtw): Likewise. + (*aarch64_ldff1_gather_ + _uxtw): Likewise. + * config/aarch64/aarch64-sve2.md (@aarch64_gather_ldnt): Likewise. + (@aarch64_gather_ldnt_ + ): Likewise. + +2023-06-21 Tamar Christina + + PR other/110329 + * doc/md.texi: Replace backslashchar. + +2023-06-21 Richard Biener + + * config/i386/i386.cc (ix86_vector_costs::finish_cost): + Overload. For masked main loops make sure the vectorization + factor isn't more than double the number of iterations. + +2023-06-21 Jan Beulich + + * config/i386/i386-expand.cc (ix86_expand_copysign): Request + value duplication by ix86_build_signbit_mask() when AVX512F and + not HFmode. + * config/i386/sse.md (*_vternlog_all): Convert to + 2-alternative form. Adjust "mode" attribute. Add "enabled" + attribute. + (*_vpternlog_1): Also permit when TARGET_AVX512F + && !TARGET_PREFER_AVX256. + (*_vpternlog_2): Likewise. + (*_vpternlog_3): Likewise. + +2023-06-21 liuhongt + + PR target/110018 + * tree-vect-stmts.cc (vectorizable_conversion): Use + intermiediate integer type for float_expr/fix_trunc_expr when + direct optab is not existed. + 2023-06-20 Tamar Christina PR bootstrap/110324 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 047f836b4f38..2cf61a4ffbf3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20230621 +20230626 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 669a2a001d58..c478ec852013 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1281,6 +1281,7 @@ C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \ # Analyzer object files ANALYZER_OBJS = \ + analyzer/access-diagram.o \ analyzer/analysis-plan.o \ analyzer/analyzer.o \ analyzer/analyzer-language.o \ @@ -1788,7 +1789,16 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \ json.o \ sbitmap.o \ vec.o input.o hash-table.o ggc-none.o memory-block.o \ - selftest.o selftest-diagnostic.o sort.o + selftest.o selftest-diagnostic.o sort.o \ + text-art/box-drawing.o \ + text-art/canvas.o \ + text-art/ruler.o \ + text-art/selftests.o \ + text-art/style.o \ + text-art/styled-string.o \ + text-art/table.o \ + text-art/theme.o \ + text-art/widget.o # Objects in libcommon-target.a, used by drivers and by the core # compiler and containing target-dependent code. diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 761674a7d488..a477da563f5d 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,151 @@ +2023-06-24 David Malcolm + + * access-diagram.cc: Add #define INCLUDE_VECTOR. + * bounds-checking.cc: Likewise. + +2023-06-22 David Malcolm + + PR analyzer/106626 + * access-diagram.cc: New file. + * access-diagram.h: New file. + * analyzer.h (class region_offset): Add default ctor. + (region_offset::make_byte_offset): New decl. + (region_offset::concrete_p): New. + (region_offset::get_concrete_byte_offset): New. + (region_offset::calc_symbolic_bit_offset): New decl. + (region_offset::calc_symbolic_byte_offset): New decl. + (region_offset::dump_to_pp): New decl. + (region_offset::dump): New decl. + (operator<, operator<=, operator>, operator>=): New decls for + region_offset. + * analyzer.opt + (-param=analyzer-text-art-string-ellipsis-threshold=): New. + (-param=analyzer-text-art-string-ellipsis-head-len=): New. + (-param=analyzer-text-art-string-ellipsis-tail-len=): New. + (-param=analyzer-text-art-ideal-canvas-width=): New. + (fanalyzer-debug-text-art): New. + * bounds-checking.cc: Include "intl.h", "diagnostic-diagram.h", + and "analyzer/access-diagram.h". + (class out_of_bounds::oob_region_creation_event_capacity): New. + (out_of_bounds::out_of_bounds): Add "model" and "sval_hint" + params. + (out_of_bounds::mark_interesting_stuff): Use the base region. + (out_of_bounds::add_region_creation_events): Use + oob_region_creation_event_capacity. + (out_of_bounds::get_dir): New pure vfunc. + (out_of_bounds::maybe_show_notes): New. + (out_of_bounds::maybe_show_diagram): New. + (out_of_bounds::make_access_diagram): New. + (out_of_bounds::m_model): New field. + (out_of_bounds::m_sval_hint): New field. + (out_of_bounds::m_region_creation_event_id): New field. + (concrete_out_of_bounds::concrete_out_of_bounds): Update for new + fields. + (concrete_past_the_end::concrete_past_the_end): Likewise. + (concrete_past_the_end::add_region_creation_events): Use + oob_region_creation_event_capacity. + (concrete_buffer_overflow::concrete_buffer_overflow): Update for + new fields. + (concrete_buffer_overflow::emit): Replace call to + maybe_describe_array_bounds with maybe_show_notes. + (concrete_buffer_overflow::get_dir): New. + (concrete_buffer_over_read::concrete_buffer_over_read): Update for + new fields. + (concrete_buffer_over_read::emit): Replace call to + maybe_describe_array_bounds with maybe_show_notes. + (concrete_buffer_overflow::get_dir): New. + (concrete_buffer_underwrite::concrete_buffer_underwrite): Update + for new fields. + (concrete_buffer_underwrite::emit): Replace call to + maybe_describe_array_bounds with maybe_show_notes. + (concrete_buffer_underwrite::get_dir): New. + (concrete_buffer_under_read::concrete_buffer_under_read): Update + for new fields. + (concrete_buffer_under_read::emit): Replace call to + maybe_describe_array_bounds with maybe_show_notes. + (concrete_buffer_under_read::get_dir): New. + (symbolic_past_the_end::symbolic_past_the_end): Update for new + fields. + (symbolic_buffer_overflow::symbolic_buffer_overflow): Likewise. + (symbolic_buffer_overflow::emit): Call maybe_show_notes. + (symbolic_buffer_overflow::get_dir): New. + (symbolic_buffer_over_read::symbolic_buffer_over_read): Update for + new fields. + (symbolic_buffer_over_read::emit): Call maybe_show_notes. + (symbolic_buffer_over_read::get_dir): New. + (region_model::check_symbolic_bounds): Add "sval_hint" param. Pass + it and sized_offset_reg to diagnostics. + (region_model::check_region_bounds): Add "sval_hint" param, passing + it to diagnostics. + * diagnostic-manager.cc + (diagnostic_manager::emit_saved_diagnostic): Pass logger to + pending_diagnostic::emit. + * engine.cc: Add logger param to pending_diagnostic::emit + implementations. + * infinite-recursion.cc: Likewise. + * kf-analyzer.cc: Likewise. + * kf.cc: Likewise. Add nullptr for new param of + check_region_for_write. + * pending-diagnostic.h: Likewise in decl. + * region-model-manager.cc + (region_model_manager::get_or_create_int_cst): Convert param from + poly_int64 to const poly_wide_int_ref &. + (region_model_manager::maybe_fold_binop): Support type being NULL + when checking for floating-point types. + Check for (X + Y) - X => Y. Be less strict about types when folding + associative ops. Check for (X + Y) * CST => (X * CST) + (Y * CST). + * region-model-manager.h + (region_model_manager::get_or_create_int_cst): Convert param from + poly_int64 to const poly_wide_int_ref &. + * region-model.cc: Add logger param to pending_diagnostic::emit + implementations. + (region_model::check_external_function_for_access_attr): Update + for new param of check_region_for_write. + (region_model::deref_rvalue): Use nullptr rather than NULL. + (region_model::get_capacity): Handle RK_STRING. + (region_model::check_region_access): Add "sval_hint" param; pass it to + check_region_bounds. + (region_model::check_region_for_write): Add "sval_hint" param; + pass it to check_region_access. + (region_model::check_region_for_read): Add NULL for new param to + check_region_access. + (region_model::set_value): Pass rhs_sval to + check_region_for_write. + (region_model::get_representative_path_var_1): Handle SK_CONSTANT + in the check for infinite recursion. + * region-model.h (region_model::check_region_for_write): Add + "sval_hint" param. + (region_model::check_region_access): Likewise. + (region_model::check_symbolic_bounds): Likewise. + (region_model::check_region_bounds): Likewise. + * region.cc (region_offset::make_byte_offset): New. + (region_offset::calc_symbolic_bit_offset): New. + (region_offset::calc_symbolic_byte_offset): New. + (region_offset::dump_to_pp): New. + (region_offset::dump): New. + (struct linear_op): New. + (operator<, operator<=, operator>, operator>=): New, for + region_offset. + (region::get_next_offset): New. + (region::get_relative_symbolic_offset): Use ptrdiff_type_node. + (field_region::get_relative_symbolic_offset): Likewise. + (element_region::get_relative_symbolic_offset): Likewise. + (bit_range_region::get_relative_symbolic_offset): Likewise. + * region.h (region::get_next_offset): New decl. + * sm-fd.cc: Add logger param to pending_diagnostic::emit + implementations. + * sm-file.cc: Likewise. + * sm-malloc.cc: Likewise. + * sm-pattern-test.cc: Likewise. + * sm-sensitive.cc: Likewise. + * sm-signal.cc: Likewise. + * sm-taint.cc: Likewise. + * store.cc (bit_range::contains_p): Allow "out" to be null. + * store.h (byte_range::get_start_bit_offset): New. + (byte_range::get_next_bit_offset): New. + * varargs.cc: Add logger param to pending_diagnostic::emit + implementations. + 2023-06-10 Tim Lange PR analyzer/109577 diff --git a/gcc/analyzer/access-diagram.cc b/gcc/analyzer/access-diagram.cc new file mode 100644 index 000000000000..467c9bdd7340 --- /dev/null +++ b/gcc/analyzer/access-diagram.cc @@ -0,0 +1,2406 @@ +/* Text art visualizations within -fanalyzer. + Copyright (C) 2023 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 +. */ + +#include "config.h" +#define INCLUDE_ALGORITHM +#define INCLUDE_MEMORY +#define INCLUDE_MAP +#define INCLUDE_SET +#define INCLUDE_VECTOR +#include "system.h" +#include "coretypes.h" +#include "coretypes.h" +#include "tree.h" +#include "function.h" +#include "basic-block.h" +#include "gimple.h" +#include "diagnostic.h" +#include "intl.h" +#include "make-unique.h" +#include "tree-diagnostic.h" /* for default_tree_printer. */ +#include "analyzer/analyzer.h" +#include "analyzer/region-model.h" +#include "analyzer/access-diagram.h" +#include "text-art/ruler.h" +#include "fold-const.h" + +#if ENABLE_ANALYZER + +/* Consider this code: + int32_t arr[10]; + arr[10] = x; + where we've emitted a buffer overflow diagnostic like this: + out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40 + + We want to emit a diagram that visualizes: + - the spatial relationship between the valid region to access, versus + the region that was actually accessed: does it overlap, was it touching, + close, or far away? Was it before or after in memory? What are the + relative sizes involved? + - the direction of the access (read vs write) + + The following code supports emitting diagrams similar to the following: + + # +--------------------------------+ + # |write from ‘x’ (type: ‘int32_t’)| + # +--------------------------------+ + # | + # | + # v + # +---------+-----------+-----------+ +--------------------------------+ + # | [0] | ... | [9] | | after valid range | + # +---------+-----------+-----------+ | | + # | ‘arr’ (type: ‘int32_t[10]’) | | | + # +---------------------------------+ +--------------------------------+ + # |~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| + # | | + # +---------+--------+ +---------+---------+ + # |capacity: 40 bytes| |overflow of 4 bytes| + # +------------------+ +-------------------+ + + where the diagram is laid out via table columns where each table column + represents either a range of bits/bytes, or is a spacing column (to highlight + the boundary between valid vs invalid accesses). The table columns can be + seen via -fanalyzer-debug-text-art. For example, here there are 5 table + columns ("tc0" through "tc4"): + + # +---------+-----------+-----------+---+--------------------------------+ + # | tc0 | tc1 | tc2 |tc3| tc4 | + # +---------+-----------+-----------+---+--------------------------------+ + # |bytes 0-3|bytes 4-35 |bytes 36-39| | bytes 40-43 | + # +---------+-----------+-----------+ +--------------------------------+ + # + # +--------------------------------+ + # |write from ‘x’ (type: ‘int32_t’)| + # +--------------------------------+ + # | + # | + # v + # +---------+-----------+-----------+ +--------------------------------+ + # | [0] | ... | [9] | | after valid range | + # +---------+-----------+-----------+ | | + # | ‘arr’ (type: ‘int32_t[10]’) | | | + # +---------------------------------+ +--------------------------------+ + # |~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| |~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~| + # | | + # +---------+--------+ +---------+---------+ + # |capacity: 40 bytes| |overflow of 4 bytes| + # +------------------+ +-------------------+ + + The diagram is built up from the following: + + # +--------------------------------+ + # | ITEM FOR SVALUE/ACCESSED REGION| + # +--------------------------------+ + # | + # | DIRECTION WIDGET + # v + # +---------------------------------+ +--------------------------------+ + # | VALID REGION | | INVALID ACCESS | + # +---------------------------------+ +--------------------------------+ + # + # | VALID-VS-INVALID RULER | + + i.e. a vbox_widget containing 4 child widgets laid out vertically: + - ALIGNED CHILD WIDGET: ITEM FOR SVALUE/ACCESSED REGION + - DIRECTION WIDGET + - ALIGNED CHILD WIDGET: VALID AND INVALID ACCESSES + - VALID-VS-INVALID RULER. + + A more complicated example, given this overflow: + char buf[100]; + strcpy (buf, LOREM_IPSUM); + + 01| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 02| |[0]|[1]|[2]|[3]|[4]|[5]| ... |[440]|[441]|[442]|[443]|[444]|[445]| + 03| +---+---+---+---+---+---+ +-----+-----+-----+-----+-----+-----+ + 04| |'L'|'o'|'r'|'e'|'m'|' '| | 'o' | 'r' | 'u' | 'm' | '.' | NUL | + 05| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 06| | string literal (type: 'char[446]') | + 07| +----------------------------------------------------------------------+ + 08| | | | | | | | | | | | | | | | + 09| | | | | | | | | | | | | | | | + 10| v v v v v v v v v v v v v v v + 11| +---+---------------------+----++--------------------------------------+ + 12| |[0]| ... |[99]|| after valid range | + 13| +---+---------------------+----+| | + 14| | 'buf' (type: 'char[100]') || | + 15| +------------------------------++--------------------------------------+ + 16| |~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~| + 17| | | + 18| +---------+---------+ +----------+----------+ + 19| |capacity: 100 bytes| |overflow of 346 bytes| + 20| +-------------------+ +---------------------+ + + which is: + + 01| ALIGNED CHILD WIDGET (lines 01-07): (string_region_spatial_item)-+-----+ + 02| |[0]|[1]|[2]|[3]|[4]|[5]| ... |[440]|[441]|[442]|[443]|[444]|[445]| + 03| +---+---+---+---+---+---+ +-----+-----+-----+-----+-----+-----+ + 04| |'L'|'o'|'r'|'e'|'m'|' '| | 'o' | 'r' | 'u' | 'm' | '.' | NUL | + 05| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 06| | string literal (type: 'char[446]') | + 07| +----------------------------------------------------------------------+ + 08| DIRECTION WIDGET (lines 08-10) | | | | | | | + 09| | | | | | | | | | | | | | | | + 10| v v v v v v v v v v v v v v v + 11| ALIGNED CHILD WIDGET (lines 11-15)-------------------------------------+ + 12| VALID REGION ... |[99]|| INVALID ACCESS | + 13| +---+---------------------+----+| | + 14| | 'buf' (type: 'char[100]') || | + 15| +------------------------------++--------------------------------------+ + 16| VALID-VS-INVALID RULER (lines 16-20): ~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~| + 17| | | + 18| +---------+---------+ +----------+----------+ + 19| |capacity: 100 bytes| |overflow of 346 bytes| + 20| +-------------------+ +---------------------+ + + We build the diagram in several phases: + - (1) we construct an access_diagram_impl widget. Within the ctor, we have + these subphases: + - (1.1) find all of the boundaries of interest + - (1.2) use the boundaries to build a bit_table_map, associating bit ranges + with table columns (e.g. "byte 0 is column 0, bytes 1-98 are column 2" etc) + - (1.3) create child widgets that share this table-based geometry + - (2) ask the widget for its size request + - (2.1) column widths and row heights for the table are computed by + access_diagram_impl::calc_req_size + - (2.2) child widgets request sizes based on these widths/heights + - (3) create a canvas of the appropriate size + - (4) paint the widget hierarchy to the canvas. */ + + +using namespace text_art; + +namespace ana { + +static styled_string +fmt_styled_string (style_manager &sm, + const char *fmt, ...) + ATTRIBUTE_GCC_DIAG(2, 3); + +static styled_string +fmt_styled_string (style_manager &sm, + const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + styled_string result + = styled_string::from_fmt_va (sm, default_tree_printer, fmt, &ap); + va_end (ap); + return result; +} + +class access_diagram_impl; +class bit_to_table_map; + +static void +pp_bit_size_t (pretty_printer *pp, bit_size_t num_bits) +{ + if (num_bits % BITS_PER_UNIT == 0) + { + byte_size_t num_bytes = num_bits / BITS_PER_UNIT; + if (num_bytes == 1) + pp_printf (pp, _("%wi byte"), num_bytes.to_uhwi ()); + else + pp_printf (pp, _("%wi bytes"), num_bytes.to_uhwi ()); + } + else + { + if (num_bits == 1) + pp_printf (pp, _("%wi bit"), num_bits.to_uhwi ()); + else + pp_printf (pp, _("%wi bits"), num_bits.to_uhwi ()); + } +} + +static styled_string +get_access_size_str (style_manager &sm, + const access_operation &op, + access_range accessed_range, + tree type) +{ + bit_size_expr num_bits; + if (accessed_range.get_size (op.m_model, &num_bits)) + { + if (type) + { + styled_string s; + + pretty_printer pp; + num_bits.print (&pp); + + if (op.m_dir == DIR_READ) + return fmt_styled_string (sm, + _("read of %qT (%s)"), + type, + pp_formatted_text (&pp)); + else + return fmt_styled_string (sm, + _("write of %qT (%s)"), + type, + pp_formatted_text (&pp)); + } + if (op.m_dir == DIR_READ) + return num_bits.get_formatted_str (sm, + _("read of %wi bit"), + _("read of %wi bits"), + _("read of %wi byte"), + _("read of %wi bytes"), + _("read of %qE bits"), + _("read of %qE bytes")); + else + return num_bits.get_formatted_str (sm, + _("write of %wi bit"), + _("write of %wi bits"), + _("write of %wi byte"), + _("write of %wi bytes"), + _("write of %qE bits"), + _("write of %qE bytes")); + } + + if (type) + { + if (op.m_dir == DIR_READ) + return fmt_styled_string (sm, _("read of %qT"), type); + else + return fmt_styled_string (sm, _("write of %qT"), type); + } + + if (op.m_dir == DIR_READ) + return styled_string (sm, _("read")); + else + return styled_string (sm, _("write")); +} + +/* Subroutine of clean_up_for_diagram. */ + +static tree +strip_any_cast (tree expr) +{ + if (TREE_CODE (expr) == NOP_EXPR + || TREE_CODE (expr) == NON_LVALUE_EXPR) + expr = TREE_OPERAND (expr, 0); + return expr; +} + +/* Subroutine of clean_up_for_diagram. */ + +static tree +remove_ssa_names (tree expr) +{ + if (TREE_CODE (expr) == SSA_NAME + && SSA_NAME_VAR (expr)) + return SSA_NAME_VAR (expr); + tree t = copy_node (expr); + for (int i = 0; i < TREE_OPERAND_LENGTH (expr); i++) + TREE_OPERAND (t, i) = remove_ssa_names (TREE_OPERAND (expr, i)); + return t; +} + +/* We want to be able to print tree expressions from the analyzer, + which is in the middle end. + + We could use the front-end pretty_printer's formatting routine, + but: + (a) some have additional state in a pretty_printer subclass, so we'd + need to clone global_dc->printer + (b) the "aka" type information added by the C and C++ frontends are + too verbose when building a diagram, and there isn't a good way to ask + for a less verbose version of them. + + Hence we use default_tree_printer. + However, we want to avoid printing SSA names, and instead print the + underlying var name. + Ideally there would be a better tree printer for use by middle end + warnings, but as workaround, this function clones a tree, replacing + SSA names with the var names. */ + +tree +clean_up_for_diagram (tree expr) +{ + tree without_ssa_names = remove_ssa_names (expr); + return strip_any_cast (without_ssa_names); +} + +/* struct bit_size_expr. */ + +text_art::styled_string +bit_size_expr::get_formatted_str (text_art::style_manager &sm, + const char *concrete_single_bit_fmt, + const char *concrete_plural_bits_fmt, + const char *concrete_single_byte_fmt, + const char *concrete_plural_bytes_fmt, + const char *symbolic_bits_fmt, + const char *symbolic_bytes_fmt) const +{ + if (TREE_CODE (m_num_bits) == INTEGER_CST) + { + bit_size_t concrete_num_bits = wi::to_offset (m_num_bits); + if (concrete_num_bits % BITS_PER_UNIT == 0) + { + byte_size_t concrete_num_bytes = concrete_num_bits / BITS_PER_UNIT; + if (concrete_num_bytes == 1) + return fmt_styled_string (sm, concrete_single_byte_fmt, + concrete_num_bytes.to_uhwi ()); + else + return fmt_styled_string (sm, concrete_plural_bytes_fmt, + concrete_num_bytes.to_uhwi ()); + } + else + { + if (concrete_num_bits == 1) + return fmt_styled_string (sm, concrete_single_bit_fmt, + concrete_num_bits.to_uhwi ()); + else + return fmt_styled_string (sm, concrete_plural_bits_fmt, + concrete_num_bits.to_uhwi ()); + } + } + else + { + if (tree bytes_expr = maybe_get_as_bytes ()) + return fmt_styled_string (sm, + symbolic_bytes_fmt, + clean_up_for_diagram (bytes_expr)); + return fmt_styled_string (sm, + symbolic_bits_fmt, + clean_up_for_diagram (m_num_bits)); + } +} + +void +bit_size_expr::print (pretty_printer *pp) const +{ + if (TREE_CODE (m_num_bits) == INTEGER_CST) + { + bit_size_t concrete_num_bits = wi::to_offset (m_num_bits); + pp_bit_size_t (pp, concrete_num_bits); + } + else + { + if (tree bytes_expr = maybe_get_as_bytes ()) + pp_printf (pp, _("%qE bytes"), bytes_expr); + else + pp_printf (pp, _("%qE bits"), m_num_bits); + } +} + +tree +bit_size_expr::maybe_get_as_bytes () const +{ + switch (TREE_CODE (m_num_bits)) + { + default: + break; + case INTEGER_CST: + { + const bit_size_t num_bits = wi::to_offset (m_num_bits); + if (num_bits % BITS_PER_UNIT != 0) + return NULL_TREE; + const bit_size_t num_bytes = num_bits / BITS_PER_UNIT; + return wide_int_to_tree (size_type_node, num_bytes); + } + break; + case PLUS_EXPR: + case MINUS_EXPR: + { + bit_size_expr op0 + = bit_size_expr (TREE_OPERAND (m_num_bits, 0)); + tree op0_as_bytes = op0.maybe_get_as_bytes (); + if (!op0_as_bytes) + return NULL_TREE; + bit_size_expr op1 + = bit_size_expr (TREE_OPERAND (m_num_bits, 1)); + tree op1_as_bytes = op1.maybe_get_as_bytes (); + if (!op1_as_bytes) + return NULL_TREE; + return fold_build2 (TREE_CODE (m_num_bits), size_type_node, + op0_as_bytes, op1_as_bytes); + } + break; + case MULT_EXPR: + { + bit_size_expr op1 + = bit_size_expr (TREE_OPERAND (m_num_bits, 1)); + if (tree op1_as_bytes = op1.maybe_get_as_bytes ()) + return fold_build2 (MULT_EXPR, size_type_node, + TREE_OPERAND (m_num_bits, 0), + op1_as_bytes); + } + break; + } + return NULL_TREE; +} + +/* struct access_range. */ + +access_range::access_range (const region *base_region, const bit_range &bits) +: m_start (region_offset::make_concrete (base_region, + bits.get_start_bit_offset ())), + m_next (region_offset::make_concrete (base_region, + bits.get_next_bit_offset ())) +{ +} + +access_range::access_range (const region *base_region, const byte_range &bytes) +: m_start (region_offset::make_concrete (base_region, + bytes.get_start_bit_offset ())), + m_next (region_offset::make_concrete (base_region, + bytes.get_next_bit_offset ())) +{ +} + +access_range::access_range (const region ®, region_model_manager *mgr) +: m_start (reg.get_offset (mgr)), + m_next (reg.get_next_offset (mgr)) +{ +} + +bool +access_range::get_size (const region_model &model, bit_size_expr *out) const +{ + tree start_expr = m_start.calc_symbolic_bit_offset (model); + if (!start_expr) + return false; + tree next_expr = m_next.calc_symbolic_bit_offset (model); + if (!next_expr) + return false; + *out = bit_size_expr (fold_build2 (MINUS_EXPR, size_type_node, + next_expr, start_expr)); + return true; +} + +bool +access_range::contains_p (const access_range &other) const +{ + return (m_start <= other.m_start + && other.m_next <= m_next); +} + +bool +access_range::empty_p () const +{ + bit_range concrete_bits (0, 0); + if (!as_concrete_bit_range (&concrete_bits)) + return false; + return concrete_bits.empty_p (); +} + +void +access_range::dump_to_pp (pretty_printer *pp, bool simple) const +{ + if (m_start.concrete_p () && m_next.concrete_p ()) + { + bit_range bits (m_start.get_bit_offset (), + m_next.get_bit_offset () - m_start.get_bit_offset ()); + bits.dump_to_pp (pp); + return; + } + pp_character (pp, '['); + m_start.dump_to_pp (pp, simple); + pp_string (pp, " to "); + m_next.dump_to_pp (pp, simple); + pp_character (pp, ')'); +} + +DEBUG_FUNCTION void +access_range::dump (bool simple) const +{ + pretty_printer pp; + pp_format_decoder (&pp) = default_tree_printer; + pp_show_color (&pp) = pp_show_color (global_dc->printer); + pp.buffer->stream = stderr; + dump_to_pp (&pp, simple); + pp_newline (&pp); + pp_flush (&pp); +} + +void +access_range::log (const char *title, logger &logger) const +{ + logger.start_log_line (); + logger.log_partial ("%s: ", title); + dump_to_pp (logger.get_printer (), true); + logger.end_log_line (); +} + +/* struct access_operation. */ + +access_range +access_operation::get_valid_bits () const +{ + const svalue *capacity_in_bytes_sval = m_model.get_capacity (m_base_region); + return access_range + (region_offset::make_concrete (m_base_region, 0), + region_offset::make_byte_offset (m_base_region, capacity_in_bytes_sval)); +} + +access_range +access_operation::get_actual_bits () const +{ + return access_range (m_reg, get_manager ()); +} + +/* If there are any bits accessed invalidly before the valid range, + return true and write their range to *OUT. + Return false if there aren't, or if there's a problem + (e.g. symbolic ranges. */ + +bool +access_operation::maybe_get_invalid_before_bits (access_range *out) const +{ + access_range valid_bits (get_valid_bits ()); + access_range actual_bits (get_actual_bits ()); + + if (actual_bits.m_start >= valid_bits.m_start) + { + /* No part of accessed range is before the valid range. */ + return false; + } + else if (actual_bits.m_next > valid_bits.m_start) + { + /* Get part of accessed range that's before the valid range. */ + *out = access_range (actual_bits.m_start, valid_bits.m_start); + return true; + } + else + { + /* Accessed range is fully before valid range. */ + *out = actual_bits; + return true; + } +} + +/* If there are any bits accessed invalidly after the valid range, + return true and write their range to *OUT. + Return false if there aren't, or if there's a problem. */ + +bool +access_operation::maybe_get_invalid_after_bits (access_range *out) const +{ + access_range valid_bits (get_valid_bits ()); + access_range actual_bits (get_actual_bits ()); + + if (actual_bits.m_next <= valid_bits.m_next) + { + /* No part of accessed range is after the valid range. */ + return false; + } + else if (actual_bits.m_start < valid_bits.m_next) + { + /* Get part of accessed range that's after the valid range. */ + *out = access_range (valid_bits.m_next, actual_bits.m_next); + return true; + } + else + { + /* Accessed range is fully after valid range. */ + *out = actual_bits; + return true; + } +} + +/* A class for capturing all of the region offsets of interest (both concrete + and symbolic), to help align everything in the diagram. + Boundaries can be soft or hard; hard boundaries are emphasized visually + (e.g. the boundary between valid vs invalid accesses). + + Offsets in the boundaries are all expressed relative to the base + region of the access_operation. */ + +class boundaries +{ +public: + enum class kind { HARD, SOFT}; + + boundaries (const region &base_reg) + : m_base_reg (base_reg) + { + } + + void add (region_offset offset, enum kind k) + { + m_all_offsets.insert (offset); + if (k == kind::HARD) + m_hard_offsets.insert (offset); + } + + void add (const access_range &range, enum kind kind) + { + add (range.m_start, kind); + add (range.m_next, kind); + } + + void add (const region ®, region_model_manager *mgr, enum kind kind) + { + add (access_range (reg.get_offset (mgr), + reg.get_next_offset (mgr)), + kind); + } + + void add (const byte_range bytes, enum kind kind) + { + add (access_range (&m_base_reg, bytes), kind); + } + + void add_all_bytes_in_range (const byte_range &bytes) + { + for (byte_offset_t byte_idx = bytes.get_start_byte_offset (); + byte_idx <= bytes.get_next_byte_offset (); + byte_idx = byte_idx + 1) + add (region_offset::make_concrete (&m_base_reg, byte_idx * 8), + kind::SOFT); + } + + void add_all_bytes_in_range (const access_range &range) + { + byte_range bytes (0, 0); + bool valid = range.as_concrete_byte_range (&bytes); + gcc_assert (valid); + add_all_bytes_in_range (bytes); + } + + void log (logger &logger) const + { + logger.log ("boundaries:"); + logger.inc_indent (); + for (auto offset : m_all_offsets) + { + enum kind k = get_kind (offset); + logger.start_log_line (); + logger.log_partial ("%s: ", (k == kind::HARD) ? "HARD" : "soft"); + offset.dump_to_pp (logger.get_printer (), true); + logger.end_log_line (); + } + logger.dec_indent (); + } + + enum kind get_kind (region_offset offset) const + { + gcc_assert (m_all_offsets.find (offset) != m_all_offsets.end ()); + if (m_hard_offsets.find (offset) != m_hard_offsets.end ()) + return kind::HARD; + else + return kind::SOFT; + } + + std::set::const_iterator begin () const + { + return m_all_offsets.begin (); + } + std::set::const_iterator end () const + { + return m_all_offsets.end (); + } + std::set::size_type size () const + { + return m_all_offsets.size (); + } + +private: + const region &m_base_reg; + std::set m_all_offsets; + std::set m_hard_offsets; +}; + +/* A widget that wraps a table but offloads column-width calculation + to a shared object, so that we can vertically line up multiple tables + and have them all align their columns. + + For example, in: + + 01| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 02| |[0]|[1]|[2]|[3]|[4]|[5]| ... |[440]|[441]|[442]|[443]|[444]|[445]| + 03| +---+---+---+---+---+---+ +-----+-----+-----+-----+-----+-----+ + 04| |'L'|'o'|'r'|'e'|'m'|' '| | 'o' | 'r' | 'u' | 'm' | '.' | NUL | + 05| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 06| | string literal (type: 'char[446]') | + 07| +----------------------------------------------------------------------+ + 08| | | | | | | | | | | | | | | | + 09| | | | | | | | | | | | | | | | + 10| v v v v v v v v v v v v v v v + 11|+---+---------------------+----++--------------------------------------+ + 12||[0]| ... |[99]|| after valid range | + 13|+---+---------------------+----+| | + 14|| 'buf' (type: 'char[100]') || | + 15|+------------------------------++--------------------------------------+ + 16||~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~| + 17| | | + 18| +---------+---------+ +----------+----------+ + 19| |capacity: 100 bytes| |overflow of 346 bytes| + 20| +-------------------+ +---------------------+ + + rows 01-07 and rows 11-15 are x_aligned_table_widget instances. */ + +class x_aligned_table_widget : public leaf_widget +{ +public: + x_aligned_table_widget (table t, + const theme &theme, + table_dimension_sizes &col_widths) + : m_table (std::move (t)), + m_theme (theme), + m_col_widths (col_widths), + m_row_heights (t.get_size ().h), + m_cell_sizes (m_col_widths, m_row_heights), + m_tg (m_table, m_cell_sizes) + { + } + + const char *get_desc () const override + { + return "x_aligned_table_widget"; + } + + canvas::size_t calc_req_size () final override + { + /* We don't compute the size requirements; + the parent should have done this. */ + return m_tg.get_canvas_size (); + } + + void paint_to_canvas (canvas &canvas) final override + { + m_table.paint_to_canvas (canvas, + get_top_left (), + m_tg, + m_theme); + } + + const table &get_table () const { return m_table; } + table_cell_sizes &get_cell_sizes () { return m_cell_sizes; } + void recalc_coords () + { + m_tg.recalc_coords (); + } + +private: + table m_table; + const theme &m_theme; + table_dimension_sizes &m_col_widths; // Reference to shared column widths + table_dimension_sizes m_row_heights; // Unique row heights + table_cell_sizes m_cell_sizes; + table_geometry m_tg; +}; + +/* A widget for printing arrows between the accessed region + and the svalue, showing the direction of the access. + + For example, in: + + 01| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 02| |[0]|[1]|[2]|[3]|[4]|[5]| ... |[440]|[441]|[442]|[443]|[444]|[445]| + 03| +---+---+---+---+---+---+ +-----+-----+-----+-----+-----+-----+ + 04| |'L'|'o'|'r'|'e'|'m'|' '| | 'o' | 'r' | 'u' | 'm' | '.' | NUL | + 05| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 06| | string literal (type: 'char[446]') | + 07| +----------------------------------------------------------------------+ + 08| | | | | | | | | | | | | | | | + 09| | | | | | | | | | | | | | | | + 10| v v v v v v v v v v v v v v v + 11|+---+---------------------+----++--------------------------------------+ + 12||[0]| ... |[99]|| after valid range | + 13|+---+---------------------+----+| | + 14|| 'buf' (type: 'char[100]') || | + 15|+------------------------------++--------------------------------------+ + 16||~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~| + 17| | | + 18| +---------+---------+ +----------+----------+ + 19| |capacity: 100 bytes| |overflow of 346 bytes| + 20| +-------------------+ +---------------------+ + + rows 8-10 are the direction widget. */ + +class direction_widget : public leaf_widget +{ +public: + direction_widget (const access_diagram_impl &dia_impl, + const bit_to_table_map &btm) + : leaf_widget (), + m_dia_impl (dia_impl), + m_btm (btm) + { + } + const char *get_desc () const override + { + return "direction_widget"; + } + canvas::size_t calc_req_size () final override + { + /* Get our width from our siblings. */ + return canvas::size_t (0, 3); + } + void paint_to_canvas (canvas &canvas) final override; + +private: + const access_diagram_impl &m_dia_impl; + const bit_to_table_map &m_btm; +}; + +/* A widget for adding an x_ruler to a diagram based on table columns, + offloading column-width calculation to shared objects, so that the ruler + lines up with other tables in the diagram. + + For example, in: + + 01| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 02| |[0]|[1]|[2]|[3]|[4]|[5]| ... |[440]|[441]|[442]|[443]|[444]|[445]| + 03| +---+---+---+---+---+---+ +-----+-----+-----+-----+-----+-----+ + 04| |'L'|'o'|'r'|'e'|'m'|' '| | 'o' | 'r' | 'u' | 'm' | '.' | NUL | + 05| +---+---+---+---+---+---+----------+-----+-----+-----+-----+-----+-----+ + 06| | string literal (type: 'char[446]') | + 07| +----------------------------------------------------------------------+ + 08| | | | | | | | | | | | | | | | + 09| | | | | | | | | | | | | | | | + 10| v v v v v v v v v v v v v v v + 11|+---+---------------------+----++--------------------------------------+ + 12||[0]| ... |[99]|| after valid range | + 13|+---+---------------------+----+| | + 14|| 'buf' (type: 'char[100]') || | + 15|+------------------------------++--------------------------------------+ + 16||~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~||~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~| + 17| | | + 18| +---------+---------+ +----------+----------+ + 19| |capacity: 100 bytes| |overflow of 346 bytes| + 20| +-------------------+ +---------------------+ + + rows 16-20 are the x_aligned_x_ruler_widget. */ + +class x_aligned_x_ruler_widget : public leaf_widget +{ +public: + x_aligned_x_ruler_widget (const access_diagram_impl &dia_impl, + const theme &theme, + table_dimension_sizes &col_widths) + : m_dia_impl (dia_impl), + m_theme (theme), + m_col_widths (col_widths) + { + } + + const char *get_desc () const override + { + return "x_aligned_ruler_widget"; + } + + void add_range (const table::range_t &x_range, + styled_string text, + style::id_t style_id) + { + m_labels.push_back (label (x_range, std::move (text), style_id)); + } + + canvas::size_t calc_req_size () final override + { + x_ruler r (make_x_ruler ()); + return r.get_size (); + } + + void paint_to_canvas (canvas &canvas) final override + { + x_ruler r (make_x_ruler ()); + r.paint_to_canvas (canvas, + get_top_left (), + m_theme); + } + +private: + struct label + { + label (const table::range_t &table_x_range, + styled_string text, + style::id_t style_id) + : m_table_x_range (table_x_range), + m_text (std::move (text)), + m_style_id (style_id) + { + } + table::range_t m_table_x_range; + styled_string m_text; + style::id_t m_style_id; + }; + + x_ruler make_x_ruler () const; + + const access_diagram_impl &m_dia_impl; + const theme &m_theme; + table_dimension_sizes &m_col_widths; + std::vector