aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog313
-rw-r--r--libgcc/Makefile.in27
-rw-r--r--libgcc/config.host19
-rw-r--r--libgcc/config/aarch64/aarch64-unwind.h40
-rw-r--r--libgcc/config/aarch64/lse-init.c17
-rw-r--r--libgcc/config/aarch64/lse.S45
-rw-r--r--libgcc/config/avr/libf7/ChangeLog4
-rw-r--r--libgcc/config/avr/libf7/t-libf74
-rw-r--r--libgcc/config/avr/t-avr10
-rw-r--r--libgcc/config/cris/libgcc-glibc.ver7
-rw-r--r--libgcc/config/cris/t-linux2
-rw-r--r--libgcc/config/i386/cpuinfo.c463
-rw-r--r--libgcc/config/i386/cpuinfo.h135
-rw-r--r--libgcc/config/i386/gnu-unwind.h107
-rw-r--r--libgcc/config/i386/morestack.S2
-rw-r--r--libgcc/config/i386/sfp-exceptions.c24
-rw-r--r--libgcc/config/ia64/divtf3.c9
-rw-r--r--libgcc/config/ia64/t-softfp-compat3
-rw-r--r--libgcc/config/libbid/ChangeLog6
-rw-r--r--libgcc/config/libbid/bid_internal.h4
-rw-r--r--libgcc/config/nvptx/atomic.c73
-rw-r--r--libgcc/config/nvptx/t-nvptx3
-rw-r--r--libgcc/config/riscv/div.S8
-rw-r--r--libgcc/config/riscv/save-restore.S13
-rw-r--r--libgcc/config/rs6000/t-aix-cxa15
-rw-r--r--libgcc/config/rs6000/t-slibgcc-aix69
-rw-r--r--libgcc/config/xtensa/unwind-dw2-xtensa.c46
-rwxr-xr-xlibgcc/configure32
-rw-r--r--libgcc/configure.ac14
-rw-r--r--libgcc/empty.mk2
-rw-r--r--libgcc/gcov.h5
-rw-r--r--libgcc/libgcov-driver-system.c2
-rw-r--r--libgcc/libgcov-driver.c178
-rw-r--r--libgcc/libgcov-interface.c126
-rw-r--r--libgcc/libgcov-merge.c103
-rw-r--r--libgcc/libgcov-profiler.c51
-rw-r--r--libgcc/libgcov-util.c127
-rw-r--r--libgcc/libgcov.h166
-rw-r--r--libgcc/unwind-dw2.c34
39 files changed, 1202 insertions, 1106 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 02b36d3..588b6f4 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,7 +1,318 @@
+2020-08-13 Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ * config/nvptx/atomic.c: New.
+ * config/nvptx/t-nvptx (LIB2ADD): Add atomic.c.
+
+2020-08-03 Ian Lance Taylor <iant@golang.org>
+
+ * config/i386/morestack.S (BACKOFF) [x86_64]: Add 2048 bytes.
+
+2020-08-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/96402
+ * config/aarch64/lse.S (__aarch64_cas16_acq_rel): Use x2, x3 instead
+ of x(tmp0), x(tmp1) in STXP arguments.
+
+2020-07-31 Maciej W. Rozycki <macro@wdc.com>
+
+ * config/riscv/save-restore.S [__riscv_xlen == 64]
+ (__riscv_save_10, __riscv_save_8, __riscv_save_6, __riscv_save_4)
+ (__riscv_save_2): Replace negative immediates used for the final
+ stack pointer adjustment with positive ones, right-shifted by 4.
+
+2020-07-31 Martin Liska <mliska@suse.cz>
+
+ * libgcov-driver.c: Add __gcov_kvp_pool
+ and __gcov_kvp_pool_index variables.
+ * libgcov.h (allocate_gcov_kvp): New.
+ (gcov_topn_add_value): Use it.
+
+2020-07-24 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/aarch64/lse.S: Add PAC property note.
+
+2020-07-23 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/96035
+ * libgcov-driver-system.c: Create gcov folders with 0777
+ so that it respects a system umask.
+
+2020-07-14 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/t-slibgcc-aix: Set BITS from compiler cpp macro.
+
+2020-07-13 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ PR target/94891
+ * config/aarch64/aarch64-unwind.h (MD_POST_EXTRACT_ROOT_ADDR): Remove.
+ (MD_POST_FROB_EH_HANDLER_ADDR): Remove.
+ (MD_POST_EXTRACT_FRAME_ADDR): Rename to ...
+ (MD_DEMANGLE_RETURN_ADDR): This.
+ (aarch64_post_extract_frame_addr): Rename to ...
+ (aarch64_demangle_return_addr): This.
+ (aarch64_post_frob_eh_handler_addr): Remove.
+ * unwind-dw2.c (uw_update_context): Demangle return address.
+ (uw_frob_return_addr): Remove.
+
+2020-07-09 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ PR target/96001
+ * config/aarch64/lse.S: Add BTI marking and related definitions,
+ and add BTI c to function entries.
+
+2020-07-09 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/aarch64/lse.S: Add stack note.
+
+2020-07-02 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/95348
+ * libgcov-driver.c (merge_one_data): Merge only profiles
+ that are not of non-zero type.
+ (write_one_data): Write counters only if there's one non-zero
+ value.
+ * libgcov-util.c (tag_function): Change signature from unsigned
+ to int.
+ (tag_blocks): Likewise.
+ (tag_arcs): Likewise.
+ (tag_counters): Likewise.
+ (tag_summary): Likewise.
+ (tag_lines): Read only if COUNTERS is non-zero.
+ (read_gcda_file): Handle negative length for COUNTERS type.
+
+2020-06-25 Martin Liska <mliska@suse.cz>
+
+ * libgcov-driver.c (merge_summary): Remove function as its name
+ is misleading and doing something different.
+ (dump_one_gcov): Add ATTRIBUTE_UNUSED for 2 args. Take read summary
+ in gcov-tool.
+ * libgcov-util.c (curr_object_summary): Remove.
+ (read_gcda_file): Remove unused curr_object_summary.
+ (gcov_merge): Merge summaries.
+ * libgcov.h: Add summary argument for gcov_info struct.
+
+2020-06-24 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/95259
+ * config/i386/cpuinfo.c: Don't include "cpuinfo.h". Include
+ "common/config/i386/i386-cpuinfo.h" and
+ "common/config/i386/cpuinfo.h".
+ (__cpu_features2): Changed to array.
+ (get_amd_cpu): Removed.
+ (get_intel_cpu): Likewise.
+ (get_available_features): Likewise.
+ (__cpu_indicator_init): Call cpu_indicator_init.
+ * config/i386/cpuinfo.h: Removed.
+
+2020-06-23 David Edelsohn <dje.gcc@gmail.com>
+
+ * Makefile.in: Remove uses of empty.mk. Use -include.
+ * config/avr/t-avr: Use -include.
+ * empty.mk: Delete.
+
+2020-06-21 David Edelsohn <dje.gcc@gmail.com>
+
+ * config.host (extra_parts): Add crtcxa_64 and crtdbase_64.
+ * config/rs6000/t-aix-cxa: Explicitly compile 32 bit with -maix32
+ and 64 bit with -maix64.
+ * config/rs6000/t-slibgcc-aix: Remove extra @multilib_dir@ level.
+ Build and install AIX-style FAT libraries.
+
+2020-06-17 Samuel Thibault <samuel.thibault@gnu.org>
+
+ * config.host (md_unwind_header) <i[34567]86-*-gnu*>: Set to
+ 'i386/gnu-unwind.h'
+ * config/i386/gnu-unwind.h: New file.
+
+2020-06-17 Martin Liska <mliska@suse.cz>
+
+ * libgcov-util.c (read_gcda_finalize): Remove const operator.
+ (merge_wrapper): Add both counts and use them properly.
+ (topn_to_memory_representation): New function.
+ (gcov_merge): Covert on disk representation to in memory
+ representation.
+ * libgcov.h: Remove const operator.
+
+2020-06-15 Max Filippov <jcmvbkbc@gmail.com>
+
+ * configure: Regenerate.
+ * configure.ac: Use AC_COMPILE_IFELSE instead of manual
+ preprocessor invocation to check for __XTENSA_CALL0_ABI__.
+
+2020-06-09 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/95494
+ * libgcov-driver.c (write_top_counters): Cast first to
+ intptr_t as sizeof(*) != sizeof(gcov_type).
+ * libgcov.h (gcov_counter_set_if_null): Remove.
+ (gcov_topn_add_value): Cast first to intptr_t and update
+ linked list directly.
+
+2020-06-09 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/unwind-dw2-xtensa.c (uw_install_context): Merge
+ with uw_install_context_1.
+
+2020-06-04 Andreas Schwab <schwab@suse.de>
+
+ PR target/59230
+ PR libfortran/59227
+ * config/ia64/t-softfp-compat (softfp_file_list): Filter out
+ soft-fp/divtf3.c.
+ (LIB2ADD): Add config/ia64/divtf3.c.
+ * config/ia64/divtf3.c: New file.
+
+2020-06-03 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/95480
+ * libgcov-profiler.c (GCOV_SUPPORTS_ATOMIC): Move to...
+ * libgcov.h (GCOV_SUPPORTS_ATOMIC): ...here.
+ (gcov_counter_add): Use GCOV_SUPPORTS_ATOMIC guard.
+ (gcov_counter_set_if_null): Likewise.
+
+2020-06-02 Jim Wilson <jimw@sifive.com>
+
+ * config/riscv/div.S (__divdi3): For negative arguments, change bgez
+ to bgtz.
+
+2020-06-02 Martin Liska <mliska@suse.cz>
+
+ * libgcov.h (gcov_topn_add_value): Use xcalloc instead
+ of xmalloc.
+
+2020-06-02 Martin Liska <mliska@suse.cz>
+
+ * libgcov-driver.c (prune_topn_counter): Remove.
+ (prune_counters): Likewise.
+ (merge_one_data): Special case TOP N counters
+ as they have variable length.
+ (write_top_counters): New.
+ (write_one_data): Special case TOP N.
+ (dump_one_gcov): Do not prune TOP N counters.
+ * libgcov-merge.c (merge_topn_values_set): Remove.
+ (__gcov_merge_topn): Use gcov_topn_add_value.
+ * libgcov-profiler.c (__gcov_topn_values_profiler_body):
+ Likewise here.
+ * libgcov.h (gcov_counter_add): New.
+ (gcov_counter_set_if_null): Likewise.
+ (gcov_topn_add_value): New.
+
+2020-06-01 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sfp-exceptions.c (struct fenv):
+ Add __attribute__ ((gcc_struct)).
+
+2020-05-29 H.J. Lu <hjl.tools@gmail.com>
+
+ PR bootstrap/95413
+ * configure: Regenerated.
+
+2020-05-28 Dong JianQiang <dongjianqiang2@huawei.com>
+
+ PR gcov-profile/95332
+ * libgcov-util.c (read_gcda_file): Call gcov_magic.
+ * libgcov.h (gcov_magic): Disable GCC poison.
+
+2020-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/95212
+ * config/i386/cpuinfo.h (processor_features): Move
+ FEATURE_AVX512VP2INTERSECT after FEATURE_AVX512BF16.
+
+2020-05-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/91695
+ * config/i386/cpuinfo.c (get_available_features): Fix VPCLMULQDQ
+ check.
+
+2020-05-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/95212
+ PR target/95220
+ * config/i386/cpuinfo.c (get_available_features): Fix
+ FEATURE_GFNI check. Also check FEATURE_AVX512VP2INTERSECT.
+ * config/i386/cpuinfo.h (processor_features): Add
+ FEATURE_AVX512VP2INTERSECT.
+
+2020-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR bootstrap/95147
+ * configure: Regenerated.
+
+2020-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure: Regenerated.
+
+2020-05-09 Hans-Peter Nilsson <hp@axis.com>
+
+ * config.host: Remove support for crisv32-*-* and cris*-*-linux.
+ * config/cris/libgcc-glibc.ver, config/cris/t-linux: Remove.
+
+2020-05-06 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sfp-exceptions.c (__math_force_eval): Remove.
+ (__math_force_eval_div): New define.
+ (__sfp_handle_exceptions): Use __math_force_eval_div to use
+ generic division to generate INVALID, DIVZERO and INEXACT
+ exceptions.
+
+2020-05-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/lse-init.c (init_have_lse_atomics): Use __getauxval
+ instead of getauxval.
+ (AT_HWCAP): Define.
+ (HWCAP_ATOMICS): Define.
+ Guard detection on __gnu_linux__.
+
+2020-05-05 Michael Meissner <meissner@linux.ibm.com>
+
+ * config.host: Delete changes meant for a private branch.
+ * config/rs6000/t-float128: Likewise.
+ * configure.ac: Likewise.
+ * configure: Likewise.
+
+2020-05-05 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/93623
+ * Makefile.in: Remove __gcov_flush.
+ * gcov.h (__gcov_flush): Remove.
+ * libgcov-interface.c (__gcov_flush): Remove.
+ (init_mx): Use renamed mutex.
+ (__gcov_lock): Likewise.
+ (__gcov_unlock): Likewise.
+ (__gcov_fork): Likewise.
+ (__gcov_flush): Remove.
+
+2020-05-05 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/93623
+ * libgcov-interface.c (__gcov_fork): Do not flush
+ and reset only in child process.
+ (__gcov_execl): Dump counters only and reset them
+ only if exec* fails.
+ (__gcov_execlp): Likewise.
+ (__gcov_execle): Likewise.
+ (__gcov_execv): Likewise.
+ (__gcov_execvp): Likewise.
+ (__gcov_execve): Likewise.
+
+2020-05-05 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/93623
+ * Makefile.in: Add _gcov_lock_unlock to LIBGCOV_INTERFACE.
+ * libgcov-interface.c (ALIAS_void_fn): Remove.
+ (__gcov_lock): New.
+ (__gcov_unlock): New.
+ (__gcov_flush): Use __gcov_lock and __gcov_unlock.
+ (__gcov_reset): Likewise.
+ (__gcov_dump): Likewise.
+ * libgcov.h (__gcov_lock): New declaration.
+ (__gcov_unlock): Likewise.
+
2020-05-01 Uroš Bizjak <ubizjak@gmail.com>
* config/i386/sfp-exceptions.c (__math_force_eval): New define.
- (__sfp_handle_exceptions): Use __math_force_eval to evaluete
+ (__sfp_handle_exceptions): Use __math_force_eval to evaluate
generic division to generate INVALID and DIVZERO exceptions.
2020-04-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 8c58cd1..278b9ff 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -373,7 +373,7 @@ gthr-default.h: $(srcdir)/$(thread_header)
-$(LN_S) $< $@
tmake_file = @tmake_file@
-include $(srcdir)/empty.mk $(tmake_file)
+-include $(tmake_file)
# Collect target defines and headers from config.host.
libgcc_tm_defines = @tm_defines@
@@ -393,7 +393,7 @@ ifeq ($(SHLIB_LINK),)
endif
ifeq ($(enable_shared),yes)
- iterator = $(srcdir)/empty.mk $(patsubst %,$(srcdir)/shared-object.mk,$(iter-items))
+ iterator = $(patsubst %,$(srcdir)/shared-object.mk,$(iter-items))
install-shared = install-shared
@@ -425,7 +425,7 @@ gen-hide-list = echo > $@
endif
ifneq ($(enable_shared),yes)
-iterator = $(srcdir)/empty.mk $(patsubst %,$(srcdir)/static-object.mk,$(iter-items))
+iterator = $(patsubst %,$(srcdir)/static-object.mk,$(iter-items))
endif
LIB2ADD += enable-execute-stack.c
@@ -522,7 +522,7 @@ iter-items := $(sifuncs) $(difuncs) $(tifuncs)
iter-labels := $(sifuncs) $(difuncs) $(difuncs)
iter-sizes := $(patsubst %,4,$(sifuncs) $(difuncs)) $(patsubst %,8,$(tifuncs))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(sifuncs) $(difuncs) $(tifuncs))
ifeq ($(enable_shared),yes)
@@ -805,7 +805,7 @@ iter-items := $(fixed-funcs)
iter-labels := $(fixed-labels)
iter-from := $(fixed-modes)
iter-to := $(fixed-modes)
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
# Add arithmetic functions to list of objects to be built
libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-funcs)))
@@ -824,7 +824,7 @@ iter-items := $(fixed-conv-funcs)
iter-labels := $(fixed-conv-labels)
iter-from := $(fixed-conv-from)
iter-to := $(fixed-conv-to)
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items))
# Add conversion functions to list of objects to be built
libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-conv-funcs)))
@@ -844,7 +844,7 @@ libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADD_ST))))
c_flags :=
iter-items := $(LIB2ADD) $(LIB2ADD_ST)
-include $(iterator)
+-include $(iterator)
ifeq ($(enable_shared),yes)
libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADD))))
@@ -862,7 +862,7 @@ libgcc-eh-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADDEHSTATIC
libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADDEHSHARED))))
iter-items := $(sort $(LIB2ADDEHSTATIC) $(LIB2ADDEHSHARED))
-include $(iterator)
+-include $(iterator)
else
# Not shared. LIB2ADDEH are added to libgcc.a.
@@ -870,7 +870,7 @@ else
libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADDEH))))
iter-items := $(LIB2ADDEH)
-include $(iterator)
+-include $(iterator)
endif
@@ -886,7 +886,7 @@ libunwind-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIBUNWIND))
endif
iter-items := $(LIBUNWIND)
-include $(iterator)
+-include $(iterator)
# Build libgcov components.
@@ -904,9 +904,10 @@ LIBGCOV_PROFILER = _gcov_interval_profiler \
_gcov_ior_profiler_atomic \
_gcov_indirect_call_profiler_v4 \
_gcov_time_profiler
-LIBGCOV_INTERFACE = _gcov_dump _gcov_flush _gcov_fork \
+LIBGCOV_INTERFACE = _gcov_dump _gcov_fork \
_gcov_execl _gcov_execlp \
- _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset
+ _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset \
+ _gcov_lock_unlock
LIBGCOV_DRIVER = _gcov
libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE))
@@ -1202,4 +1203,4 @@ install-strip: install
# configure.
.NOEXPORT:
-include $(srcdir)/empty.mk $(wildcard *.dep)
+-include $(wildcard *.dep)
diff --git a/libgcc/config.host b/libgcc/config.host
index 1ff4159..7a3e29d 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -112,9 +112,6 @@ bpf-*-*)
;;
cr16-*-*)
;;
-crisv32-*-*)
- cpu_type=cris
- ;;
csky*-*-*)
cpu_type=csky
;;
@@ -577,15 +574,9 @@ cr16-*-elf)
tmake_file="${tmake_file} cr16/t-cr16 cr16/t-crtlibid t-fdpbit"
extra_parts="$extra_parts crti.o crtn.o crtlibid.o"
;;
-crisv32-*-elf)
- tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp"
- ;;
cris-*-elf)
tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-elfmulti"
;;
-cris-*-linux* | crisv32-*-linux*)
- tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-linux"
- ;;
csky-*-elf*)
tmake_file="csky/t-csky t-fdpbit"
extra_parts="$extra_parts crti.o crtn.o"
@@ -743,10 +734,16 @@ i[34567]86-*-linux*)
tm_file="${tm_file} i386/elf-lib.h"
md_unwind_header=i386/linux-unwind.h
;;
-i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
+i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-kopensolaris*-gnu)
+ extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+ tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
+ tm_file="${tm_file} i386/elf-lib.h"
+ ;;
+i[34567]86-*-gnu*)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
tm_file="${tm_file} i386/elf-lib.h"
+ md_unwind_header=i386/gnu-unwind.h
;;
x86_64-*-linux*)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
@@ -1276,7 +1273,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
md_unwind_header=rs6000/aix-unwind.h
tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble rs6000/t-aix-cxa"
- extra_parts="crtcxa.o crtcxa_s.o crtdbase.o"
+ extra_parts="crtcxa.o crtcxa_s.o crtdbase.o crtcxa_64.o crtcxa_64_s.o crtdbase_64.o"
;;
rl78-*-elf)
tmake_file="$tm_file t-fdpbit rl78/t-rl78"
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index ed84a96..3c5f85b 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -27,11 +27,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DWARF_REGNUM_AARCH64_RA_STATE 34
-#define MD_POST_EXTRACT_ROOT_ADDR(addr) __builtin_aarch64_xpaclri (addr)
-#define MD_POST_EXTRACT_FRAME_ADDR(context, fs, addr) \
- aarch64_post_extract_frame_addr (context, fs, addr)
-#define MD_POST_FROB_EH_HANDLER_ADDR(current, target, addr) \
- aarch64_post_frob_eh_handler_addr (current, target, addr)
+#define MD_DEMANGLE_RETURN_ADDR(context, fs, addr) \
+ aarch64_demangle_return_addr (context, fs, addr)
#define MD_FROB_UPDATE_CONTEXT(context, fs) \
aarch64_frob_update_context (context, fs)
@@ -52,14 +49,15 @@ aarch64_cie_signed_with_b_key (struct _Unwind_Context *context)
return 0;
}
-/* Do AArch64 private extraction on ADDR based on context info CONTEXT and
- unwind frame info FS. If ADDR is signed, we do address authentication on it
- using CFA of current frame. */
+/* Do AArch64 private extraction on ADDR_WORD based on context info CONTEXT and
+ unwind frame info FS. If ADDR_WORD is signed, we do address authentication
+ on it using CFA of current frame. */
static inline void *
-aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
- _Unwind_FrameState *fs, void *addr)
+aarch64_demangle_return_addr (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs, _Unwind_Word addr_word)
{
+ void *addr = (void *)addr_word;
if (context->flags & RA_SIGNED_BIT)
{
_Unwind_Word salt = (_Unwind_Word) context->cfa;
@@ -71,28 +69,6 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
return addr;
}
-/* Do AArch64 private frob on exception handler's address HANDLER_ADDR before
- installing it into current context CURRENT. TARGET is currently not used.
- We need to sign exception handler's address if CURRENT itself is signed. */
-
-static inline void *
-aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
- struct _Unwind_Context *target
- ATTRIBUTE_UNUSED,
- void *handler_addr)
-{
- if (current->flags & RA_SIGNED_BIT)
- {
- if (aarch64_cie_signed_with_b_key (current))
- return __builtin_aarch64_pacib1716 (handler_addr,
- (_Unwind_Word) current->cfa);
- return __builtin_aarch64_pacia1716 (handler_addr,
- (_Unwind_Word) current->cfa);
- }
- else
- return handler_addr;
-}
-
/* Do AArch64 private initialization on CONTEXT based on frame info FS. Mark
CONTEXT as return address signed if bit 0 of DWARF_REGNUM_AARCH64_RA_STATE is
set. */
diff --git a/libgcc/config/aarch64/lse-init.c b/libgcc/config/aarch64/lse-init.c
index 74acef2..00e9ab8 100644
--- a/libgcc/config/aarch64/lse-init.c
+++ b/libgcc/config/aarch64/lse-init.c
@@ -29,19 +29,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
_Bool __aarch64_have_lse_atomics
__attribute__((visibility("hidden"), nocommon));
-/* Disable initialization of __aarch64_have_lse_atomics during bootstrap. */
-#if !defined(inhibit_libc) && defined(HAVE_SYS_AUXV_H)
-# include <sys/auxv.h>
+/* Gate availability of __getauxval on glibc. All AArch64-supporting glibc
+ versions support it. */
+#ifdef __gnu_linux__
-/* Disable initialization if the system headers are too old. */
-# if defined(AT_HWCAP) && defined(HWCAP_ATOMICS)
+# define AT_HWCAP 16
+# define HWCAP_ATOMICS (1 << 8)
+
+unsigned long int __getauxval (unsigned long int);
static void __attribute__((constructor))
init_have_lse_atomics (void)
{
- unsigned long hwcap = getauxval (AT_HWCAP);
+ unsigned long hwcap = __getauxval (AT_HWCAP);
__aarch64_have_lse_atomics = (hwcap & HWCAP_ATOMICS) != 0;
}
-# endif /* HWCAP */
-#endif /* inhibit_libc */
+#endif /* __gnu_linux__ */
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index f3ccf5c..7496b8b 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -136,6 +136,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define tmp1 17
#define tmp2 15
+#define BTI_C hint 34
+
/* Start and end a function. */
.macro STARTFN name
.text
@@ -145,6 +147,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.type \name, %function
.cfi_startproc
\name:
+ BTI_C
.endm
.macro ENDFN name
@@ -200,7 +203,7 @@ STARTFN NAME(cas)
cmp x0, x(tmp0)
ccmp x1, x(tmp1), #0, eq
bne 1f
- STXP w(tmp2), x(tmp0), x(tmp1), [x4]
+ STXP w(tmp2), x2, x3, [x4]
cbnz w(tmp2), 0b
1: ret
@@ -274,3 +277,43 @@ STARTFN NAME(LDNM)
ENDFN NAME(LDNM)
#endif
+
+/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code. */
+#define FEATURE_1_AND 0xc0000000
+#define FEATURE_1_BTI 1
+#define FEATURE_1_PAC 2
+
+/* Supported features based on the code generation options. */
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+# define BTI_FLAG FEATURE_1_BTI
+#else
+# define BTI_FLAG 0
+#endif
+
+#if __ARM_FEATURE_PAC_DEFAULT & 3
+# define PAC_FLAG FEATURE_1_PAC
+#else
+# define PAC_FLAG 0
+#endif
+
+/* Add a NT_GNU_PROPERTY_TYPE_0 note. */
+#define GNU_PROPERTY(type, value) \
+ .section .note.gnu.property, "a"; \
+ .p2align 3; \
+ .word 4; \
+ .word 16; \
+ .word 5; \
+ .asciz "GNU"; \
+ .word type; \
+ .word 4; \
+ .word value; \
+ .word 0;
+
+#if defined(__linux__) || defined(__FreeBSD__)
+.section .note.GNU-stack, "", %progbits
+
+/* Add GNU property note if built with branch protection. */
+# if (BTI_FLAG|PAC_FLAG) != 0
+GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
+# endif
+#endif
diff --git a/libgcc/config/avr/libf7/ChangeLog b/libgcc/config/avr/libf7/ChangeLog
index 1ec4735..d24215e 100644
--- a/libgcc/config/avr/libf7/ChangeLog
+++ b/libgcc/config/avr/libf7/ChangeLog
@@ -1,3 +1,7 @@
+2020-06-23 David Edelsohn <dje.gcc@gmail.com>
+
+ * t-libf7: Use -include.
+
2020-01-08 Georg-Johann Lay <avr@gjlay.de>
Implement 64-bit double functions.
diff --git a/libgcc/config/avr/libf7/t-libf7 b/libgcc/config/avr/libf7/t-libf7
index 92a27eb..30aa280 100644
--- a/libgcc/config/avr/libf7/t-libf7
+++ b/libgcc/config/avr/libf7/t-libf7
@@ -125,7 +125,7 @@ f7_parts := $(F7_C_PARTS)
iter-items := $(f7_parts)
iter-labels := $(f7_parts)
-include $(srcdir)/empty.mk $(patsubst %,$(libf7)/libf7-c-object.mk,$(iter-items))
+-include $(patsubst %,$(libf7)/libf7-c-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,f7_c_%$(objext),$(F7_C_PARTS))
@@ -136,7 +136,7 @@ f7_parts := $(F7_ASM_PARTS)
iter-items := $(f7_parts)
iter-labels := $(f7_parts)
-include $(srcdir)/empty.mk $(patsubst %,$(libf7)/libf7-asm-object.mk,$(iter-items))
+-include $(patsubst %,$(libf7)/libf7-asm-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,f7_asm_%$(objext),$(F7_ASM_PARTS))
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index e4f867b..ed84b3f 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -132,7 +132,7 @@ iter-labels := $(siintfuncs16)
iter-sizes := $(patsubst %,2,$(siintfuncs16)) $(patsubst %,2,$(hiintfuncs16))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(hiintfuncs16))
ifeq ($(enable_shared),yes)
@@ -167,7 +167,7 @@ iter-items := $(round_funcs)
iter-labels := $(round_suffix)
iter-flags := $(patsubst %,-DL_round,$(iter-items))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(round_funcs))
@@ -181,7 +181,7 @@ iter-items := $(clrsb_funcs)
iter-labels := $(clrsb_funcs)
iter-flags := $(patsubst %,-DL_clrsb,$(iter-items))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(clrsb_funcs))
@@ -195,7 +195,7 @@ iter-items := $(countls_funcs)
iter-labels := $(countls_modes)
iter-flags := $(patsubst %,-DL_countls,$(iter-items))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(countls_funcs))
@@ -209,7 +209,7 @@ iter-items := $(countlsu_funcs)
iter-labels := $(countlsu_modes)
iter-flags := $(patsubst %,-DL_countlsu,$(iter-items))
-include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
libgcc-objects += $(patsubst %,%$(objext),$(countlsu_funcs))
diff --git a/libgcc/config/cris/libgcc-glibc.ver b/libgcc/config/cris/libgcc-glibc.ver
deleted file mode 100644
index e35de83..0000000
--- a/libgcc/config/cris/libgcc-glibc.ver
+++ /dev/null
@@ -1,7 +0,0 @@
-GCC_4.3 {
- __Mul
- __Div
- __Udiv
- __Mod
- __Umod
-}
diff --git a/libgcc/config/cris/t-linux b/libgcc/config/cris/t-linux
deleted file mode 100644
index 8c7f4d4..0000000
--- a/libgcc/config/cris/t-linux
+++ /dev/null
@@ -1,2 +0,0 @@
-# Override t-linux default.
-SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/cris/libgcc-glibc.ver
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index 00322c5..7218952 100644
--- a/libgcc/config/i386/cpuinfo.c
+++ b/libgcc/config/i386/cpuinfo.c
@@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "cpuid.h"
#include "tsystem.h"
#include "auto-target.h"
-#include "cpuinfo.h"
+#include "common/config/i386/i386-cpuinfo.h"
+#include "common/config/i386/cpuinfo.h"
#ifdef HAVE_INIT_PRIORITY
#define CONSTRUCTOR_PRIORITY (101)
@@ -39,384 +40,14 @@ int __cpu_indicator_init (void)
struct __processor_model __cpu_model = { };
-#ifndef SHARED
/* We want to move away from __cpu_model in libgcc_s.so.1 and the
size of __cpu_model is part of ABI. So, new features that don't
fit into __cpu_model.__cpu_features[0] go into extra variables
- in libgcc.a only, preferrably hidden. */
-unsigned int __cpu_features2;
-#endif
-
-
-/* Get the specific type of AMD CPU. */
-
-static void
-get_amd_cpu (unsigned int family, unsigned int model)
-{
- switch (family)
- {
- /* AMD Family 10h. */
- case 0x10:
- __cpu_model.__cpu_type = AMDFAM10H;
- switch (model)
- {
- case 0x2:
- /* Barcelona. */
- __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA;
- break;
- case 0x4:
- /* Shanghai. */
- __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI;
- break;
- case 0x8:
- /* Istanbul. */
- __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL;
- break;
- default:
- break;
- }
- break;
- /* AMD Family 14h "btver1". */
- case 0x14:
- __cpu_model.__cpu_type = AMD_BTVER1;
- break;
- /* AMD Family 15h "Bulldozer". */
- case 0x15:
- __cpu_model.__cpu_type = AMDFAM15H;
-
- if (model == 0x2)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
- /* Bulldozer version 1. */
- else if (model <= 0xf)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1;
- /* Bulldozer version 2 "Piledriver" */
- else if (model <= 0x2f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2;
- /* Bulldozer version 3 "Steamroller" */
- else if (model <= 0x4f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3;
- /* Bulldozer version 4 "Excavator" */
- else if (model <= 0x7f)
- __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4;
- break;
- /* AMD Family 16h "btver2" */
- case 0x16:
- __cpu_model.__cpu_type = AMD_BTVER2;
- break;
- case 0x17:
- __cpu_model.__cpu_type = AMDFAM17H;
- /* AMD family 17h version 1. */
- if (model <= 0x1f)
- __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1;
- if (model >= 0x30)
- __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2;
- break;
- default:
- break;
- }
-}
-
-/* Get the specific type of Intel CPU. */
-
-static void
-get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id)
-{
- /* Parse family and model only if brand ID is 0. */
- if (brand_id == 0)
- {
- switch (family)
- {
- case 0x5:
- /* Pentium. */
- break;
- case 0x6:
- switch (model)
- {
- case 0x1c:
- case 0x26:
- /* Bonnell. */
- __cpu_model.__cpu_type = INTEL_BONNELL;
- break;
- case 0x37:
- case 0x4a:
- case 0x4d:
- case 0x5a:
- case 0x5d:
- /* Silvermont. */
- __cpu_model.__cpu_type = INTEL_SILVERMONT;
- break;
- case 0x5c:
- case 0x5f:
- /* Goldmont. */
- __cpu_model.__cpu_type = INTEL_GOLDMONT;
- break;
- case 0x7a:
- /* Goldmont Plus. */
- __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS;
- break;
- case 0x57:
- /* Knights Landing. */
- __cpu_model.__cpu_type = INTEL_KNL;
- break;
- case 0x85:
- /* Knights Mill. */
- __cpu_model.__cpu_type = INTEL_KNM;
- break;
- case 0x1a:
- case 0x1e:
- case 0x1f:
- case 0x2e:
- /* Nehalem. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM;
- break;
- case 0x25:
- case 0x2c:
- case 0x2f:
- /* Westmere. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE;
- break;
- case 0x2a:
- case 0x2d:
- /* Sandy Bridge. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE;
- break;
- case 0x3a:
- case 0x3e:
- /* Ivy Bridge. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE;
- break;
- case 0x3c:
- case 0x3f:
- case 0x45:
- case 0x46:
- /* Haswell. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL;
- break;
- case 0x3d:
- case 0x47:
- case 0x4f:
- case 0x56:
- /* Broadwell. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL;
- break;
- case 0x4e:
- case 0x5e:
- /* Skylake. */
- case 0x8e:
- case 0x9e:
- /* Kaby Lake. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE;
- break;
- case 0x55:
- {
- unsigned int eax, ebx, ecx, edx;
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- if (ecx & bit_AVX512VNNI)
- /* Cascade Lake. */
- __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE;
- else
- /* Skylake with AVX-512 support. */
- __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512;
- }
- break;
- case 0x66:
- /* Cannon Lake. */
- __cpu_model.__cpu_type = INTEL_COREI7;
- __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE;
- break;
- case 0x17:
- case 0x1d:
- /* Penryn. */
- case 0x0f:
- /* Merom. */
- __cpu_model.__cpu_type = INTEL_CORE2;
- break;
- default:
- break;
- }
- break;
- default:
- /* We have no idea. */
- break;
- }
- }
-}
-
-/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is
- the max possible level of CPUID insn. */
-static void
-get_available_features (unsigned int ecx, unsigned int edx,
- int max_cpuid_level)
-{
- unsigned int eax, ebx;
- unsigned int ext_level;
-
- unsigned int features = 0;
- unsigned int features2 = 0;
-
- /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
-#define XCR_XFEATURE_ENABLED_MASK 0x0
-#define XSTATE_FP 0x1
-#define XSTATE_SSE 0x2
-#define XSTATE_YMM 0x4
-#define XSTATE_OPMASK 0x20
-#define XSTATE_ZMM 0x40
-#define XSTATE_HI_ZMM 0x80
-
-#define XCR_AVX_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM)
-#define XCR_AVX512F_ENABLED_MASK \
- (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM)
-
- /* Check if AVX and AVX512 are usable. */
- int avx_usable = 0;
- int avx512_usable = 0;
- if ((ecx & bit_OSXSAVE))
- {
- /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and
- ZMM16-ZMM31 states are supported by OSXSAVE. */
- unsigned int xcrlow;
- unsigned int xcrhigh;
- asm (".byte 0x0f, 0x01, 0xd0"
- : "=a" (xcrlow), "=d" (xcrhigh)
- : "c" (XCR_XFEATURE_ENABLED_MASK));
- if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK)
- {
- avx_usable = 1;
- avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK)
- == XCR_AVX512F_ENABLED_MASK);
- }
- }
-
-#define set_feature(f) \
- do \
- { \
- if (f < 32) \
- features |= (1U << (f & 31)); \
- else \
- features2 |= (1U << ((f - 32) & 31)); \
- } \
- while (0)
-
- if (edx & bit_CMOV)
- set_feature (FEATURE_CMOV);
- if (edx & bit_MMX)
- set_feature (FEATURE_MMX);
- if (edx & bit_SSE)
- set_feature (FEATURE_SSE);
- if (edx & bit_SSE2)
- set_feature (FEATURE_SSE2);
- if (ecx & bit_POPCNT)
- set_feature (FEATURE_POPCNT);
- if (ecx & bit_AES)
- set_feature (FEATURE_AES);
- if (ecx & bit_PCLMUL)
- set_feature (FEATURE_PCLMUL);
- if (ecx & bit_SSE3)
- set_feature (FEATURE_SSE3);
- if (ecx & bit_SSSE3)
- set_feature (FEATURE_SSSE3);
- if (ecx & bit_SSE4_1)
- set_feature (FEATURE_SSE4_1);
- if (ecx & bit_SSE4_2)
- set_feature (FEATURE_SSE4_2);
- if (avx_usable)
- {
- if (ecx & bit_AVX)
- set_feature (FEATURE_AVX);
- if (ecx & bit_FMA)
- set_feature (FEATURE_FMA);
- }
-
- /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */
- if (max_cpuid_level >= 7)
- {
- __cpuid_count (7, 0, eax, ebx, ecx, edx);
- if (ebx & bit_BMI)
- set_feature (FEATURE_BMI);
- if (avx_usable)
- {
- if (ebx & bit_AVX2)
- set_feature (FEATURE_AVX2);
- }
- if (ebx & bit_BMI2)
- set_feature (FEATURE_BMI2);
- if (avx512_usable)
- {
- if (ebx & bit_AVX512F)
- set_feature (FEATURE_AVX512F);
- if (ebx & bit_AVX512VL)
- set_feature (FEATURE_AVX512VL);
- if (ebx & bit_AVX512BW)
- set_feature (FEATURE_AVX512BW);
- if (ebx & bit_AVX512DQ)
- set_feature (FEATURE_AVX512DQ);
- if (ebx & bit_AVX512CD)
- set_feature (FEATURE_AVX512CD);
- if (ebx & bit_AVX512PF)
- set_feature (FEATURE_AVX512PF);
- if (ebx & bit_AVX512ER)
- set_feature (FEATURE_AVX512ER);
- if (ebx & bit_AVX512IFMA)
- set_feature (FEATURE_AVX512IFMA);
- if (ecx & bit_AVX512VBMI)
- set_feature (FEATURE_AVX512VBMI);
- if (ecx & bit_AVX512VBMI2)
- set_feature (FEATURE_AVX512VBMI2);
- if (ecx & bit_GFNI)
- set_feature (FEATURE_GFNI);
- if (ecx & bit_VPCLMULQDQ)
- set_feature (FEATURE_VPCLMULQDQ);
- if (ecx & bit_AVX512VNNI)
- set_feature (FEATURE_AVX512VNNI);
- if (ecx & bit_AVX512BITALG)
- set_feature (FEATURE_AVX512BITALG);
- if (ecx & bit_AVX512VPOPCNTDQ)
- set_feature (FEATURE_AVX512VPOPCNTDQ);
- if (edx & bit_AVX5124VNNIW)
- set_feature (FEATURE_AVX5124VNNIW);
- if (edx & bit_AVX5124FMAPS)
- set_feature (FEATURE_AVX5124FMAPS);
+ in libgcc.a only, preferably hidden.
- __cpuid_count (7, 1, eax, ebx, ecx, edx);
- if (eax & bit_AVX512BF16)
- set_feature (FEATURE_AVX512BF16);
- }
- }
-
- /* Check cpuid level of extended features. */
- __cpuid (0x80000000, ext_level, ebx, ecx, edx);
-
- if (ext_level >= 0x80000001)
- {
- __cpuid (0x80000001, eax, ebx, ecx, edx);
-
- if (ecx & bit_SSE4a)
- set_feature (FEATURE_SSE4_A);
- if (avx_usable)
- {
- if (ecx & bit_FMA4)
- set_feature (FEATURE_FMA4);
- if (ecx & bit_XOP)
- set_feature (FEATURE_XOP);
- }
- }
-
- __cpu_model.__cpu_features[0] = features;
-#ifndef SHARED
- __cpu_features2 = features2;
-#else
- (void) features2;
-#endif
-}
+ NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or
+ smaller array, it can only access the first few elements. */
+unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES];
/* A constructor function that is sets __cpu_model and __cpu_features with
the right values. This needs to run only once. This constructor is
@@ -427,85 +58,9 @@ get_available_features (unsigned int ecx, unsigned int edx,
int __attribute__ ((constructor CONSTRUCTOR_PRIORITY))
__cpu_indicator_init (void)
{
- unsigned int eax, ebx, ecx, edx;
-
- int max_level;
- unsigned int vendor;
- unsigned int model, family, brand_id;
- unsigned int extended_model, extended_family;
-
- /* This function needs to run just once. */
- if (__cpu_model.__cpu_vendor)
- return 0;
-
- /* Assume cpuid insn present. Run in level 0 to get vendor id. */
- if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx))
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- vendor = ebx;
- max_level = eax;
-
- if (max_level < 1)
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
- {
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
- return -1;
- }
-
- model = (eax >> 4) & 0x0f;
- family = (eax >> 8) & 0x0f;
- brand_id = ebx & 0xff;
- extended_model = (eax >> 12) & 0xf0;
- extended_family = (eax >> 20) & 0xff;
-
- if (vendor == signature_INTEL_ebx)
- {
- /* Adjust model and family for Intel CPUS. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
- else if (family == 0x06)
- model += extended_model;
-
- /* Get CPU type. */
- get_intel_cpu (family, model, brand_id);
- /* Find available features. */
- get_available_features (ecx, edx, max_level);
- __cpu_model.__cpu_vendor = VENDOR_INTEL;
- }
- else if (vendor == signature_AMD_ebx)
- {
- /* Adjust model and family for AMD CPUS. */
- if (family == 0x0f)
- {
- family += extended_family;
- model += extended_model;
- }
-
- /* Get CPU type. */
- get_amd_cpu (family, model);
- /* Find available features. */
- get_available_features (ecx, edx, max_level);
- __cpu_model.__cpu_vendor = VENDOR_AMD;
- }
- else
- __cpu_model.__cpu_vendor = VENDOR_OTHER;
-
- gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX);
- gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX);
- gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
-
- return 0;
+ struct __processor_model2 cpu_model2;
+ return cpu_indicator_init (&__cpu_model, &cpu_model2,
+ __cpu_features2);
}
#if defined SHARED && defined USE_ELF_SYMVER
diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h
deleted file mode 100644
index 41c4a49..0000000
--- a/libgcc/config/i386/cpuinfo.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Get CPU type and Features for x86 processors.
- Copyright (C) 2012-2020 Free Software Foundation, Inc.
- Contributed by Sriraman Tallam (tmsriram@google.com)
-
-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
-<http://www.gnu.org/licenses/>. */
-
-/* Processor Vendor and Models. */
-
-enum processor_vendor
-{
- VENDOR_INTEL = 1,
- VENDOR_AMD,
- VENDOR_OTHER,
- VENDOR_MAX
-};
-
-/* Any new types or subtypes have to be inserted at the end. */
-
-enum processor_types
-{
- INTEL_BONNELL = 1,
- INTEL_CORE2,
- INTEL_COREI7,
- AMDFAM10H,
- AMDFAM15H,
- INTEL_SILVERMONT,
- INTEL_KNL,
- AMD_BTVER1,
- AMD_BTVER2,
- AMDFAM17H,
- INTEL_KNM,
- INTEL_GOLDMONT,
- INTEL_GOLDMONT_PLUS,
- INTEL_TREMONT,
- CPU_TYPE_MAX
-};
-
-enum processor_subtypes
-{
- INTEL_COREI7_NEHALEM = 1,
- INTEL_COREI7_WESTMERE,
- INTEL_COREI7_SANDYBRIDGE,
- AMDFAM10H_BARCELONA,
- AMDFAM10H_SHANGHAI,
- AMDFAM10H_ISTANBUL,
- AMDFAM15H_BDVER1,
- AMDFAM15H_BDVER2,
- AMDFAM15H_BDVER3,
- AMDFAM15H_BDVER4,
- AMDFAM17H_ZNVER1,
- INTEL_COREI7_IVYBRIDGE,
- INTEL_COREI7_HASWELL,
- INTEL_COREI7_BROADWELL,
- INTEL_COREI7_SKYLAKE,
- INTEL_COREI7_SKYLAKE_AVX512,
- INTEL_COREI7_CANNONLAKE,
- INTEL_COREI7_ICELAKE_CLIENT,
- INTEL_COREI7_ICELAKE_SERVER,
- AMDFAM17H_ZNVER2,
- INTEL_COREI7_CASCADELAKE,
- INTEL_COREI7_TIGERLAKE,
- INTEL_COREI7_COOPERLAKE,
- CPU_SUBTYPE_MAX
-};
-
-/* ISA Features supported. New features have to be inserted at the end. */
-
-enum processor_features
-{
- FEATURE_CMOV = 0,
- FEATURE_MMX,
- FEATURE_POPCNT,
- FEATURE_SSE,
- FEATURE_SSE2,
- FEATURE_SSE3,
- FEATURE_SSSE3,
- FEATURE_SSE4_1,
- FEATURE_SSE4_2,
- FEATURE_AVX,
- FEATURE_AVX2,
- FEATURE_SSE4_A,
- FEATURE_FMA4,
- FEATURE_XOP,
- FEATURE_FMA,
- FEATURE_AVX512F,
- FEATURE_BMI,
- FEATURE_BMI2,
- FEATURE_AES,
- FEATURE_PCLMUL,
- FEATURE_AVX512VL,
- FEATURE_AVX512BW,
- FEATURE_AVX512DQ,
- FEATURE_AVX512CD,
- FEATURE_AVX512ER,
- FEATURE_AVX512PF,
- FEATURE_AVX512VBMI,
- FEATURE_AVX512IFMA,
- FEATURE_AVX5124VNNIW,
- FEATURE_AVX5124FMAPS,
- FEATURE_AVX512VPOPCNTDQ,
- FEATURE_AVX512VBMI2,
- FEATURE_GFNI,
- FEATURE_VPCLMULQDQ,
- FEATURE_AVX512VNNI,
- FEATURE_AVX512BITALG,
- FEATURE_AVX512BF16
-};
-
-extern struct __processor_model
-{
- unsigned int __cpu_vendor;
- unsigned int __cpu_type;
- unsigned int __cpu_subtype;
- unsigned int __cpu_features[1];
-} __cpu_model;
-extern unsigned int __cpu_features2;
diff --git a/libgcc/config/i386/gnu-unwind.h b/libgcc/config/i386/gnu-unwind.h
new file mode 100644
index 0000000..db47f0a
--- /dev/null
+++ b/libgcc/config/i386/gnu-unwind.h
@@ -0,0 +1,107 @@
+/* DWARF2 EH unwinding support for GNU Hurd: x86.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Contributed by Samuel Thibault <samuel.thibault@gnu.org>
+
+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
+<http://www.gnu.org/licenses/>. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#ifndef inhibit_libc
+
+#include <signal.h>
+
+#define MD_FALLBACK_FRAME_STATE_FOR x86_gnu_fallback_frame_state
+
+static _Unwind_Reason_Code
+x86_gnu_fallback_frame_state
+(struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ struct handler_args {
+ int signo;
+ int sigcode;
+ struct sigcontext *scp;
+ } *handler_args;
+ struct sigcontext *scp;
+ unsigned long usp;
+
+/*
+ * i386 sigtramp frame we are looking for follows.
+ * (see glibc/sysdeps/mach/hurd/i386/trampoline.c assembly)
+ *
+ * rpc_wait_trampoline:
+ * 0: b8 e7 ff ff ff mov $-25,%eax mach_msg_trap
+ * 5: 9a 00 00 00 00 07 00 lcall $7,$0
+ * 12: 89 01 movl %eax, (%ecx)
+ * 14: 89 dc movl %ebx, %esp switch to signal stack
+ *
+ * trampoline:
+ * 16: ff d2 call *%edx call the handler function
+ * RA HERE
+ * 18: 83 c4 0c addl $12, %esp pop its args
+ * 21: c3 ret return to sigreturn
+ *
+ * firewall:
+ * 22: f4 hlt
+ */
+
+ if (!( *(unsigned int *)(context->ra ) == 0xc30cc483
+ && *(unsigned char *)(context->ra + 4) == 0xf4
+
+ && *(unsigned int *)(context->ra - 4) == 0xd2ffdc89
+ && *(unsigned int *)(context->ra - 8) == 0x01890007
+ && *(unsigned int *)(context->ra - 12) == 0x00000000
+ && *(unsigned int *)(context->ra - 16) == 0x9affffff
+ && *(unsigned short *)(context->ra - 18) == 0xe7b8))
+ return _URC_END_OF_STACK;
+
+ handler_args = context->cfa;
+ scp = handler_args->scp;
+ usp = scp->sc_uesp;
+
+ fs->regs.cfa_how = CFA_REG_OFFSET;
+ fs->regs.cfa_reg = 4;
+ fs->regs.cfa_offset = usp - (unsigned long) context->cfa;
+
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = (unsigned long)&scp->sc_eax - usp;
+ fs->regs.reg[1].how = REG_SAVED_OFFSET;
+ fs->regs.reg[1].loc.offset = (unsigned long)&scp->sc_ecx - usp;
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (unsigned long)&scp->sc_edx - usp;
+ fs->regs.reg[3].how = REG_SAVED_OFFSET;
+ fs->regs.reg[3].loc.offset = (unsigned long)&scp->sc_ebx - usp;
+ fs->regs.reg[5].how = REG_SAVED_OFFSET;
+ fs->regs.reg[5].loc.offset = (unsigned long)&scp->sc_ebp - usp;
+ fs->regs.reg[6].how = REG_SAVED_OFFSET;
+ fs->regs.reg[6].loc.offset = (unsigned long)&scp->sc_esi - usp;
+ fs->regs.reg[7].how = REG_SAVED_OFFSET;
+ fs->regs.reg[7].loc.offset = (unsigned long)&scp->sc_edi - usp;
+ fs->regs.reg[8].how = REG_SAVED_OFFSET;
+ fs->regs.reg[8].loc.offset = (unsigned long)&scp->sc_eip - usp;
+ fs->retaddr_column = 8;
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+}
+
+#endif /* ifndef inhibit_libc */
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 519bbbc..1c31783 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -79,7 +79,7 @@
#ifndef __x86_64__
#define BACKOFF (1024)
#else
-#define BACKOFF (1536)
+#define BACKOFF (3584)
#endif
diff --git a/libgcc/config/i386/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c
index 4b3a7a0..3aed0af 100644
--- a/libgcc/config/i386/sfp-exceptions.c
+++ b/libgcc/config/i386/sfp-exceptions.c
@@ -39,25 +39,28 @@ struct fenv
unsigned int __data_offset;
unsigned short int __data_selector;
unsigned short int __unused5;
-};
+} __attribute__ ((gcc_struct));
#ifdef __SSE_MATH__
-# define __math_force_eval(x) asm volatile ("" : : "x" (x));
+# define __math_force_eval_div(x, y) \
+ do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0)
#else
-# define __math_force_eval(x) asm volatile ("" : : "f" (x));
+# define __math_force_eval_div(x, y) \
+ do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0)
#endif
void
__sfp_handle_exceptions (int _fex)
{
+ struct fenv temp;
+
if (_fex & FP_EX_INVALID)
{
float f = 0.0f;
- __math_force_eval (f / f);
+ __math_force_eval_div (f, f);
}
if (_fex & FP_EX_DENORM)
{
- struct fenv temp;
asm volatile ("fnstenv\t%0" : "=m" (temp));
temp.__status_word |= FP_EX_DENORM;
asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -66,11 +69,10 @@ __sfp_handle_exceptions (int _fex)
if (_fex & FP_EX_DIVZERO)
{
float f = 1.0f, g = 0.0f;
- __math_force_eval (f / g);
+ __math_force_eval_div (f, g);
}
if (_fex & FP_EX_OVERFLOW)
{
- struct fenv temp;
asm volatile ("fnstenv\t%0" : "=m" (temp));
temp.__status_word |= FP_EX_OVERFLOW;
asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -78,7 +80,6 @@ __sfp_handle_exceptions (int _fex)
}
if (_fex & FP_EX_UNDERFLOW)
{
- struct fenv temp;
asm volatile ("fnstenv\t%0" : "=m" (temp));
temp.__status_word |= FP_EX_UNDERFLOW;
asm volatile ("fldenv\t%0" : : "m" (temp));
@@ -87,12 +88,7 @@ __sfp_handle_exceptions (int _fex)
if (_fex & FP_EX_INEXACT)
{
float f = 1.0f, g = 3.0f;
-#ifdef __SSE_MATH__
- asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
-#else
- asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g));
- /* No need for fwait, exception is triggered by emitted fstp. */
-#endif
+ __math_force_eval_div (f, g);
}
}
#endif
diff --git a/libgcc/config/ia64/divtf3.c b/libgcc/config/ia64/divtf3.c
new file mode 100644
index 0000000..e1afa29
--- /dev/null
+++ b/libgcc/config/ia64/divtf3.c
@@ -0,0 +1,9 @@
+#ifdef SHARED
+#define __divtf3 __divtf3_shared
+#endif
+
+#include "soft-fp/divtf3.c"
+
+#ifdef SHARED
+asm (".symver __divtf3_shared, __divtf3@@GCC_4.4.0");
+#endif
diff --git a/libgcc/config/ia64/t-softfp-compat b/libgcc/config/ia64/t-softfp-compat
index 00f45d5..38bcea7 100644
--- a/libgcc/config/ia64/t-softfp-compat
+++ b/libgcc/config/ia64/t-softfp-compat
@@ -5,3 +5,6 @@ libgcc1-tf-functions = __divxf3 _fixtfdi _fixunstfdi _floatditf
LIB1ASMFUNCS := $(filter-out $(libgcc1-tf-functions), $(LIB1ASMFUNCS))
libgcc1-tf-compats = $(addsuffix .S, $(libgcc1-tf-functions))
LIB2ADD += $(addprefix $(srcdir)/config/ia64/, $(libgcc1-tf-compats))
+# Wrap divtf3.c to set the default symbol version
+softfp_file_list := $(filter-out $(srcdir)/soft-fp/divtf3.c, $(softfp_file_list))
+LIB2ADD += $(srcdir)/config/ia64/divtf3.c
diff --git a/libgcc/config/libbid/ChangeLog b/libgcc/config/libbid/ChangeLog
index 0920863..a1a9f46 100644
--- a/libgcc/config/libbid/ChangeLog
+++ b/libgcc/config/libbid/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-05 Martin Liska <mliska@suse.cz>
+
+ PR libgcc/92565
+ * bid_internal.h (handle_UF_128_rem): Remove unused variable.
+ (handle_UF_128): Likewise.
+
2020-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years.
diff --git a/libgcc/config/libbid/bid_internal.h b/libgcc/config/libbid/bid_internal.h
index cef36a9..9baa098 100644
--- a/libgcc/config/libbid/bid_internal.h
+++ b/libgcc/config/libbid/bid_internal.h
@@ -1540,8 +1540,6 @@ handle_UF_128_rem (UINT128 * pres, UINT64 sgn, int expon, UINT128 CQ,
__shr_128 (CQ, Qh, amount);
}
- expon = 0;
-
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
#ifndef IEEE_ROUND_NEAREST
if (!(*prounding_mode))
@@ -1676,8 +1674,6 @@ handle_UF_128 (UINT128 * pres, UINT64 sgn, int expon, UINT128 CQ,
__shr_128 (CQ, Qh, amount);
}
- expon = 0;
-
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
#ifndef IEEE_ROUND_NEAREST
if (!(*prounding_mode))
diff --git a/libgcc/config/nvptx/atomic.c b/libgcc/config/nvptx/atomic.c
new file mode 100644
index 0000000..e1ea078
--- /dev/null
+++ b/libgcc/config/nvptx/atomic.c
@@ -0,0 +1,73 @@
+/* NVPTX atomic operations
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ Contributed by Mentor Graphics.
+
+ This file 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.
+
+ This file 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+
+/* Implement __sync_val_compare_and_swap and __sync_bool_compare_and_swap
+ for 1 and 2-byte values (which are not natively supported) in terms of
+ __sync_val_compare_and_swap for 4-byte values (which is supported).
+ This assumes that the contents of the word surrounding the subword
+ value that we are interested in are accessible as well (which should
+ normally be the case). Note that if the contents of the word surrounding
+ the subword changes between the __sync_val_compare_and_swap_4 and the
+ preceeding load of oldword, while the subword does not, the implementation
+ loops, which may manifest worst-case as a hang. */
+
+#define __SYNC_SUBWORD_COMPARE_AND_SWAP(TYPE, SIZE) \
+ \
+TYPE \
+__sync_val_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval) \
+{ \
+ unsigned int *wordptr = (unsigned int *)((__UINTPTR_TYPE__ ) ptr & ~3UL); \
+ int shift = ((__UINTPTR_TYPE__ ) ptr & 3UL) * 8; \
+ unsigned int valmask = (1 << (SIZE * 8)) - 1; \
+ unsigned int wordmask = ~(valmask << shift); \
+ unsigned int oldword = *wordptr; \
+ for (;;) \
+ { \
+ TYPE prevval = (oldword >> shift) & valmask; \
+ /* Exit if the subword value previously read from memory is not */ \
+ /* equal to the expected value OLDVAL. */ \
+ if (__builtin_expect (prevval != oldval, 0)) \
+ return prevval; \
+ unsigned int newword = oldword & wordmask; \
+ newword |= ((unsigned int) newval) << shift; \
+ unsigned int prevword \
+ = __sync_val_compare_and_swap_4 (wordptr, oldword, newword); \
+ /* Exit only if the compare-and-swap succeeds on the whole word */ \
+ /* (i.e. the contents of *WORDPTR have not changed since the last */ \
+ /* memory read). */ \
+ if (__builtin_expect (prevword == oldword, 1)) \
+ return oldval; \
+ oldword = prevword; \
+ } \
+} \
+ \
+bool \
+__sync_bool_compare_and_swap_##SIZE (TYPE *ptr, TYPE oldval, TYPE newval) \
+{ \
+ return __sync_val_compare_and_swap_##SIZE (ptr, oldval, newval) == oldval; \
+}
+
+__SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned char, 1)
+__SYNC_SUBWORD_COMPARE_AND_SWAP (unsigned short, 2)
diff --git a/libgcc/config/nvptx/t-nvptx b/libgcc/config/nvptx/t-nvptx
index c4d20c9..ede0bf0 100644
--- a/libgcc/config/nvptx/t-nvptx
+++ b/libgcc/config/nvptx/t-nvptx
@@ -1,5 +1,6 @@
LIB2ADD=$(srcdir)/config/nvptx/reduction.c \
- $(srcdir)/config/nvptx/mgomp.c
+ $(srcdir)/config/nvptx/mgomp.c \
+ $(srcdir)/config/nvptx/atomic.c
LIB2ADDEH=
LIB2FUNCS_EXCLUDE=__main
diff --git a/libgcc/config/riscv/div.S b/libgcc/config/riscv/div.S
index 151f8e2..1723432 100644
--- a/libgcc/config/riscv/div.S
+++ b/libgcc/config/riscv/div.S
@@ -107,10 +107,12 @@ FUNC_END (__umoddi3)
/* Handle negative arguments to __divdi3. */
.L10:
neg a0, a0
- bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
+ /* Zero is handled as a negative so that the result will not be inverted. */
+ bgtz a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
+
neg a1, a1
- j __udivdi3 /* Compute __udivdi3(-a0, -a1). */
-.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
+ j __udivdi3 /* Compute __udivdi3(-a0, -a1). */
+.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
neg a1, a1
.L12:
move t0, ra
diff --git a/libgcc/config/riscv/save-restore.S b/libgcc/config/riscv/save-restore.S
index 7212165..e510009 100644
--- a/libgcc/config/riscv/save-restore.S
+++ b/libgcc/config/riscv/save-restore.S
@@ -45,7 +45,7 @@ FUNC_BEGIN (__riscv_save_10)
.cfi_restore 27
addi sp, sp, -112
.cfi_def_cfa_offset 112
- li t1, -16
+ li t1, 1
.Ls10:
sd s10, 16(sp)
.cfi_offset 26, -96
@@ -60,7 +60,7 @@ FUNC_BEGIN (__riscv_save_8)
.cfi_restore 27
addi sp, sp, -112
.cfi_def_cfa_offset 112
- li t1, -32
+ li t1, 2
.Ls8:
sd s8, 32(sp)
.cfi_offset 24, -80
@@ -77,7 +77,7 @@ FUNC_BEGIN (__riscv_save_6)
.cfi_restore 27
addi sp, sp, -112
.cfi_def_cfa_offset 112
- li t1, -48
+ li t1, 3
.Ls6:
sd s6, 48(sp)
.cfi_offset 22, -64
@@ -99,7 +99,7 @@ FUNC_BEGIN (__riscv_save_4)
.cfi_restore 27
addi sp, sp, -112
.cfi_def_cfa_offset 112
- li t1, -64
+ li t1, 4
.Ls4:
sd s4, 64(sp)
.cfi_offset 20, -48
@@ -123,7 +123,7 @@ FUNC_BEGIN (__riscv_save_2)
.cfi_restore 27
addi sp, sp, -112
.cfi_def_cfa_offset 112
- li t1, -80
+ li t1, 5
.Ls2:
sd s2, 80(sp)
.cfi_offset 18, -32
@@ -133,9 +133,10 @@ FUNC_BEGIN (__riscv_save_2)
.cfi_offset 8, -16
sd ra, 104(sp)
.cfi_offset 1, -8
+ slli t1, t1, 4
# CFA info is not correct in next 2 instruction since t1's
# value is depend on how may register really save.
- sub sp, sp, t1
+ add sp, sp, t1
jr t0
.cfi_endproc
FUNC_END (__riscv_save_12)
diff --git a/libgcc/config/rs6000/t-aix-cxa b/libgcc/config/rs6000/t-aix-cxa
index d7e6638..0e1bccb 100644
--- a/libgcc/config/rs6000/t-aix-cxa
+++ b/libgcc/config/rs6000/t-aix-cxa
@@ -8,10 +8,19 @@ LIB2ADD_ST += $(srcdir)/config/rs6000/aixinitfini.c
SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-aix-cxa.ver
crtdbase.o: $(srcdir)/config/rs6000/crtdbase.S
- $(crt_compile) -c $<
+ $(crt_compile) -maix32 -c $<
crtcxa.o: $(srcdir)/config/rs6000/crtcxa.c
- $(crt_compile) -c $<
+ $(crt_compile) -maix32 -c $<
crtcxa_s.o: $(srcdir)/config/rs6000/crtcxa.c
- $(crt_compile) -DSHARED -c $<
+ $(crt_compile) -maix32 -DSHARED -c $<
+
+crtdbase_64.o: $(srcdir)/config/rs6000/crtdbase.S
+ $(crt_compile) -maix64 -c $<
+
+crtcxa_64.o: $(srcdir)/config/rs6000/crtcxa.c
+ $(crt_compile) -maix64 -c $<
+
+crtcxa_64_s.o: $(srcdir)/config/rs6000/crtcxa.c
+ $(crt_compile) -maix64 -DSHARED -c $<
diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix
index 11db9ef..b3bdda6 100644
--- a/libgcc/config/rs6000/t-slibgcc-aix
+++ b/libgcc/config/rs6000/t-slibgcc-aix
@@ -37,48 +37,44 @@ SHLIB_SONAME = @shlib_base_name@.so.$(SHLIB_SOVERSION)
SHLIB_LINK = \
if test svr4 != $(with_aix_soname) ; then \
$(CC) $(LIBGCC2_CFLAGS) -shared -Wl,-bnortl -nodefaultlibs \
- -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
+ -Wl,-bE:@shlib_map_file@ -o shr.o \
@multilib_flags@ @shlib_objs@ -lc \
`case @multilib_dir@ in \
*pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
- rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
- $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/shr.o ; \
- mv @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/@shlib_base_name@.a ; \
- rm -f @multilib_dir@/shr.o ; \
+ rm -f tmp-@shlib_base_name@.a ; \
+ $(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a shr.o ; \
+ mv tmp-@shlib_base_name@.a @shlib_base_name@.a ; \
+ rm -f shr.o ; \
fi ; \
if test aix != $(with_aix_soname) ; then \
case @multilib_dir@ in *64*) shr='shr_64' ;; *) shr='shr' ;; esac ; \
$(CC) $(LIBGCC2_CFLAGS) -shared -Wl,-G -nodefaultlibs \
- -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/$$shr.o \
+ -Wl,-bE:@shlib_map_file@ -o $$shr.o \
@multilib_flags@ @shlib_objs@ -lc \
`case @multilib_dir@ in \
*pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
- $(STRIP_FOR_TARGET) -X32_64 -e @multilib_dir@/$$shr.o ; \
+ $(STRIP_FOR_TARGET) -X32_64 -e $$shr.o ; \
{ echo "\#! $(SHLIB_SONAME)($$shr.o)" ; \
case @multilib_dir@ in *64*) echo '\# 64' ;; *) echo '\# 32' ;; esac ; \
cat @shlib_map_file@ ; \
- } > @multilib_dir@/$$shr.imp ; \
- rm -f @multilib_dir@/tmp-$(SHLIB_SONAME) ; \
- $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-$(SHLIB_SONAME) \
- @multilib_dir@/$$shr.imp @multilib_dir@/$$shr.o ; \
- mv @multilib_dir@/tmp-$(SHLIB_SONAME) \
- @multilib_dir@/$(SHLIB_SONAME) ; \
- rm -f @multilib_dir@/@shlib_base_name@.so ; \
- $(LN_S) $(SHLIB_SONAME) @multilib_dir@/@shlib_base_name@.so ; \
- rm -f @multilib_dir@/$$shr.imp @multilib_dir@/$$shr.o ; \
+ } > $$shr.imp ; \
+ rm -f tmp-$(SHLIB_SONAME) ; \
+ $(AR_CREATE_FOR_TARGET) tmp-$(SHLIB_SONAME) $$shr.imp $$shr.o ; \
+ mv tmp-$(SHLIB_SONAME) $(SHLIB_SONAME) ; \
+ rm -f @shlib_base_name@.so ; \
+ $(LN_S) $(SHLIB_SONAME) @shlib_base_name@.so ; \
+ rm -f $$shr.imp $$shr.o ; \
fi
SHLIB_INSTALL = \
$(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
if test svr4 != $(with_aix_soname) ; then \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
+ $(INSTALL_DATA) @shlib_base_name@.a \
$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \
fi ; \
if test aix != $(with_aix_soname) ; then \
- $(INSTALL_DATA) @multilib_dir@/$(SHLIB_SONAME) \
+ $(INSTALL_DATA) $(SHLIB_SONAME) \
$(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \
rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so ; \
$(LN_S) $(SHLIB_SONAME) \
@@ -91,3 +87,36 @@ SHLIB_NM_FLAGS = -Bpg -X32_64
# Either 32-bit and 64-bit objects in archives.
AR_FLAGS_FOR_TARGET = -X32_64
+
+# Build and install AIX-style FAT libraries
+ifeq ($(MULTIBUILDTOP),)
+BITS=$(shell if test -z "`$(CC) -x c -E /dev/null -g3 -o - | grep 64BIT`" ; then \
+ echo '64'; else echo '32'; fi)
+all: all-multi
+ifeq ($(enable_shared),yes)
+ ar -X$(BITS) x ../ppc$(BITS)/libgcc/libgcc_s.a shr.o
+ ar -X$(BITS) rc ./libgcc_s.a shr.o
+ rm -f shr.o
+ ar -X$(BITS) x ../pthread/ppc$(BITS)/libgcc/libgcc_s.a shr.o
+ ar -X$(BITS) rc ../pthread/libgcc/libgcc_s.a shr.o
+ rm -f shr.o
+endif
+ ar -X$(BITS) rc libgcc.a \
+ $(addprefix ../ppc$(BITS)/libgcc/,$(libgcc-objects))
+ ar -X$(BITS) rc libgcc_eh.a \
+ $(addprefix ../ppc$(BITS)/libgcc/,$(libgcc-eh-objects))
+ ar -X$(BITS) rc ../pthread/libgcc/libgcc.a \
+ $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcc-objects))
+ ar -X$(BITS) rc ../pthread/libgcc/libgcc_eh.a \
+ $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcc-eh-objects))
+ifeq ($(enable_gcov),yes)
+ ar -X$(BITS) rc libgcov.a \
+ $(addprefix ../ppc$(BITS)/libgcc/,$(libgcov-objects))
+ ar -X$(BITS) rc ../pthread/libgcc/libgcov.a \
+ $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcov-objects))
+endif
+ $(MAKE) install-leaf DESTDIR=$(gcc_objdir) \
+ slibdir= libsubdir= MULTIOSDIR=$(MULTIDIR)
+ cp ../pthread/libgcc/libgcc_s.a ../../gcc/pthread/
+ cp ../pthread/libgcc/libgcc_eh.a ../../gcc/pthread/
+endif
diff --git a/libgcc/config/xtensa/unwind-dw2-xtensa.c b/libgcc/config/xtensa/unwind-dw2-xtensa.c
index 056182a..8a6a44a 100644
--- a/libgcc/config/xtensa/unwind-dw2-xtensa.c
+++ b/libgcc/config/xtensa/unwind-dw2-xtensa.c
@@ -481,37 +481,35 @@ uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
/* Install TARGET into CURRENT so that we can return to it. This is a
macro because __builtin_eh_return must be invoked in the context of
- our caller. */
+ our caller, and also because spilling registers of the caller before
+ the context installation may result in reload of wrong register values
+ after the context installation due to the change of the stack pointer
+ in the base save area. This spilling may be caused by an interrupt
+ handler on baremetal host. */
-#define uw_install_context(CURRENT, TARGET, FRAMES) \
+#define uw_install_context(CURRENT, TARGET, FRAMES) \
do \
{ \
- long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
- __builtin_eh_return (offset, handler); \
+ long i; \
+ \
+ /* The eh_return insn assumes a window size of 8, so don't bother \
+ copying the save areas for registers a8-a15 since they won't be \
+ reloaded. */ \
+ for (i = 0; i < 2; ++i) \
+ { \
+ _Unwind_Word *c = (CURRENT)->reg[i]; \
+ _Unwind_Word *t = (TARGET)->reg[i]; \
+ int j; \
+ \
+ if (t && c && t != c) \
+ for (j = 0; j < 4; ++j) \
+ *c++ = *t++; \
+ } \
+ __builtin_eh_return (0, handler); \
} \
while (0)
-static long
-uw_install_context_1 (struct _Unwind_Context *current,
- struct _Unwind_Context *target)
-{
- long i;
-
- /* The eh_return insn assumes a window size of 8, so don't bother copying
- the save areas for registers a8-a15 since they won't be reloaded. */
- for (i = 0; i < 2; ++i)
- {
- void *c = current->reg[i];
- void *t = target->reg[i];
-
- if (t && c && t != c)
- memcpy (c, t, 4 * sizeof (_Unwind_Word));
- }
-
- return 0;
-}
-
static inline _Unwind_Ptr
uw_identify_context (struct _Unwind_Context *context)
{
diff --git a/libgcc/configure b/libgcc/configure
index 26bf757..284e4db 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -1353,7 +1353,7 @@ Optional Features:
enable decimal float extension to C. Selecting 'bid'
or 'dpd' choses which decimal floating point format
to use
- --enable-cet enable Intel CET in target libraries [default=no]
+ --enable-cet enable Intel CET in target libraries [default=auto]
--enable-explicit-exception-frame-registration
register exception tables explicitly at module
start, for use e.g. for compatibility with
@@ -4900,19 +4900,22 @@ if test "${enable_cet+set}" = set; then :
esac
else
- enable_cet=no
+ enable_cet=auto
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CET support" >&5
$as_echo_n "checking for CET support... " >&6; }
+# NB: Avoid nested save_CFLAGS and save_LDFLAGS.
case "$host" in
i[34567]86-*-linux* | x86_64-*-linux*)
case "$enable_cet" in
auto)
# Check if target supports multi-byte NOPs
# and if assembler supports CET insn.
+ cet_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fcf-protection"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -4936,6 +4939,7 @@ else
enable_cet=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$cet_save_CFLAGS"
;;
yes)
# Check if assembler supports CET.
@@ -5326,19 +5330,17 @@ esac
# This is after config.host so we can augment tmake_file.
case ${host} in
xtensa*-*)
- cat > conftest.c <<EOF
- #ifdef __XTENSA_CALL0_ABI__
- #error
- #endif
-EOF
- if { ac_try='${CC-cc} -E -o conftest.i conftest.c 1>&5'
- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then
- tmake_file="${tmake_file} xtensa/t-windowed"
- fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __XTENSA_CALL0_ABI__
+ #error
+ #endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tmake_file="${tmake_file} xtensa/t-windowed"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;;
esac
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index bff6e54..ef0d799 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -515,14 +515,12 @@ AC_SUBST(solaris_ld_v2_maps)
# This is after config.host so we can augment tmake_file.
case ${host} in
xtensa*-*)
- cat > conftest.c <<EOF
- #ifdef __XTENSA_CALL0_ABI__
- #error
- #endif
-EOF
- if AC_TRY_COMMAND(${CC-cc} -E -o conftest.i conftest.c 1>&AS_MESSAGE_LOG_FD); then
- tmake_file="${tmake_file} xtensa/t-windowed"
- fi
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [#ifdef __XTENSA_CALL0_ABI__
+ #error
+ #endif
+ ])],
+ [tmake_file="${tmake_file} xtensa/t-windowed"])
;;
esac
diff --git a/libgcc/empty.mk b/libgcc/empty.mk
deleted file mode 100644
index 7b1d97b..0000000
--- a/libgcc/empty.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-# Empty. This file exists to suppress errors in the parent Makefile
-# when a variable (e.g. LIB2ADD) is empty.
diff --git a/libgcc/gcov.h b/libgcc/gcov.h
index f158191..0e3eed3 100644
--- a/libgcc/gcov.h
+++ b/libgcc/gcov.h
@@ -33,9 +33,4 @@ extern void __gcov_reset (void);
extern void __gcov_dump (void);
-/* Write profile information to a file and reset counters to zero.
- The function does operations under a mutex. */
-
-extern void __gcov_flush (void);
-
#endif /* GCC_GCOV_H */
diff --git a/libgcc/libgcov-driver-system.c b/libgcc/libgcov-driver-system.c
index 031f057..216992a 100644
--- a/libgcc/libgcov-driver-system.c
+++ b/libgcc/libgcov-driver-system.c
@@ -115,7 +115,7 @@ create_file_directory (char *filename)
/* Try to make directory if it doesn't already exist. */
if (access (filename, F_OK) == -1
#ifdef TARGET_POSIX_IO
- && mkdir (filename, 0755) == -1
+ && mkdir (filename, 0777) == -1
#else
#ifdef mkdir
#undef mkdir
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index fb32073..5891426 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -213,51 +213,6 @@ static struct gcov_fn_buffer *fn_buffer;
/* Including system dependent components. */
#include "libgcov-driver-system.c"
-/* Prune TOP N value COUNTERS. It's needed in order to preserve
- reproducibility of builds. */
-
-static void
-prune_topn_counter (gcov_type *counters, gcov_type all)
-{
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- if (counters[2 * i + 1] < all)
- {
- counters[2 * i] = 0;
- counters[2 * i + 1] = 0;
- }
-}
-
-/* Prune counters so that they are ready to store or merge. */
-
-static void
-prune_counters (struct gcov_info *gi)
-{
- for (unsigned i = 0; i < gi->n_functions; i++)
- {
- const struct gcov_fn_info *gfi = gi->functions[i];
- const struct gcov_ctr_info *ci = gfi->ctrs;
-
- for (unsigned j = 0; j < GCOV_COUNTERS; j++)
- {
- if (gi->merge[j] == NULL)
- continue;
-
- if (gi->merge[j] == __gcov_merge_topn)
- {
- gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS));
- for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS);
- k++)
- {
- gcov_type *counters
- = ci->values + (k * GCOV_TOPN_VALUES_COUNTERS);
- prune_topn_counter (counters + 1, *counters);
- }
- }
- ci++;
- }
- }
-}
-
/* This function merges counters in GI_PTR to an existing gcda file.
Return 0 on success.
Return -1 on error. In this case, caller will goto read_fatal. */
@@ -346,16 +301,21 @@ merge_one_data (const char *filename,
if (!merge)
continue;
- tag = gcov_read_unsigned ();
- length = gcov_read_unsigned ();
- if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
- || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
- goto read_mismatch;
- (*merge) (ci_ptr->values, ci_ptr->num);
- ci_ptr++;
- }
+ tag = gcov_read_unsigned ();
+ int read_length = (int)gcov_read_unsigned ();
+ length = abs (read_length);
+ if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
+ || (length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)
+ && t_ix != GCOV_COUNTER_V_TOPN
+ && t_ix != GCOV_COUNTER_V_INDIR))
+ goto read_mismatch;
+ /* Merging with all zero counters does not make sense. */
+ if (read_length > 0)
+ (*merge) (ci_ptr->values, ci_ptr->num);
+ ci_ptr++;
+ }
if ((error = gcov_is_error ()))
- goto read_error;
+ goto read_error;
}
if (tag)
@@ -374,6 +334,37 @@ read_error:
return -1;
}
+/* Store all TOP N counters where each has a dynamic length. */
+
+static void
+write_top_counters (const struct gcov_ctr_info *ci_ptr,
+ unsigned t_ix,
+ gcov_unsigned_t n_counts)
+{
+ unsigned counters = n_counts / GCOV_TOPN_MEM_COUNTERS;
+ gcc_assert (n_counts % GCOV_TOPN_MEM_COUNTERS == 0);
+ unsigned pair_total = 0;
+ for (unsigned i = 0; i < counters; i++)
+ pair_total += ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1];
+ unsigned disk_size = GCOV_TOPN_DISK_COUNTERS * counters + 2 * pair_total;
+ gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
+ GCOV_TAG_COUNTER_LENGTH (disk_size));
+
+ for (unsigned i = 0; i < counters; i++)
+ {
+ gcov_type pair_count = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1];
+ gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]);
+ gcov_write_counter (pair_count);
+ gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2];
+ for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start;
+ node != NULL; node = node->next)
+ {
+ gcov_write_counter (node->value);
+ gcov_write_counter (node->count);
+ }
+ }
+}
+
/* Write counters in GI_PTR and the summary in PRG to a gcda file. In
the case of appending to an existing file, SUMMARY_POS will be non-zero.
We will write the file starting from SUMMAY_POS. */
@@ -426,20 +417,40 @@ write_one_data (const struct gcov_info *gi_ptr,
ci_ptr = gfi_ptr->ctrs;
for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
{
- gcov_unsigned_t n_counts;
- gcov_type *c_ptr;
+ gcov_position_t n_counts;
- if (!gi_ptr->merge[t_ix])
- continue;
+ if (!gi_ptr->merge[t_ix])
+ continue;
- n_counts = ci_ptr->num;
- gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
- GCOV_TAG_COUNTER_LENGTH (n_counts));
- c_ptr = ci_ptr->values;
- while (n_counts--)
- gcov_write_counter (*c_ptr++);
- ci_ptr++;
- }
+ n_counts = ci_ptr->num;
+
+ if (gi_ptr->merge[t_ix] == __gcov_merge_topn)
+ write_top_counters (ci_ptr, t_ix, n_counts);
+ else
+ {
+ /* Do not stream when all counters are zero. */
+ int all_zeros = 1;
+ for (unsigned i = 0; i < n_counts; i++)
+ if (ci_ptr->values[i] != 0)
+ {
+ all_zeros = 0;
+ break;
+ }
+
+ if (all_zeros)
+ gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
+ GCOV_TAG_COUNTER_LENGTH (-n_counts));
+ else
+ {
+ gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
+ GCOV_TAG_COUNTER_LENGTH (n_counts));
+ for (unsigned i = 0; i < n_counts; i++)
+ gcov_write_counter (ci_ptr->values[i]);
+ }
+ }
+
+ ci_ptr++;
+ }
if (buffered)
fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
}
@@ -447,19 +458,6 @@ write_one_data (const struct gcov_info *gi_ptr,
gcov_write_unsigned (0);
}
-/* Helper function for merging summary. */
-
-static void
-merge_summary (int run_counted, struct gcov_summary *summary,
- gcov_type run_max)
-{
- if (!run_counted)
- {
- summary->runs++;
- summary->sum_max += run_max;
- }
-}
-
/* Dump the coverage counts for one gcov_info object. We merge with existing
counts when possible, to avoid growing the .da files ad infinitum. We use
this program's checksum to make sure we only accumulate whole program
@@ -469,16 +467,14 @@ merge_summary (int run_counted, struct gcov_summary *summary,
static void
dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
- unsigned run_counted, gcov_type run_max)
+ unsigned run_counted ATTRIBUTE_UNUSED,
+ gcov_type run_max ATTRIBUTE_UNUSED)
{
struct gcov_summary summary = {};
int error;
gcov_unsigned_t tag;
fn_buffer = 0;
- /* Prune current counters before we merge them. */
- prune_counters (gi_ptr);
-
error = gcov_exit_open_gcda_file (gi_ptr, gf);
if (error == -1)
return;
@@ -500,7 +496,15 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
gcov_rewrite ();
- merge_summary (run_counted, &summary, run_max);
+#if !IN_GCOV_TOOL
+ if (!run_counted)
+ {
+ summary.runs++;
+ summary.sum_max += run_max;
+ }
+#else
+ summary = gi_ptr->summary;
+#endif
write_one_data (gi_ptr, &summary);
/* fall through */
@@ -584,6 +588,12 @@ struct gcov_root __gcov_root;
struct gcov_master __gcov_master =
{GCOV_VERSION, 0};
+/* Pool of pre-allocated gcov_kvp strutures. */
+struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
+
+/* Index to first free gcov_kvp in the pool. */
+unsigned __gcov_kvp_pool_index;
+
void
__gcov_exit (void)
{
diff --git a/libgcc/libgcov-interface.c b/libgcc/libgcov-interface.c
index 048b902..3a8a5bf 100644
--- a/libgcc/libgcov-interface.c
+++ b/libgcc/libgcov-interface.c
@@ -28,10 +28,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if defined(inhibit_libc)
-#ifdef L_gcov_flush
-void __gcov_flush (void) {}
-#endif
-
#ifdef L_gcov_reset
void __gcov_reset (void) {}
#endif
@@ -42,28 +38,19 @@ void __gcov_dump (void) {}
#else
-/* Some functions we want to bind in this dynamic object, but have an
- overridable global alias. Unfortunately not all targets support
- aliases, so we just have a forwarding function. That'll be tail
- called, so the cost is a single jump instruction.*/
-
-#define ALIAS_void_fn(src,dst) \
- void dst (void) \
- { src (); }
-
-extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN;
+extern __gthread_mutex_t __gcov_mx ATTRIBUTE_HIDDEN;
-#ifdef L_gcov_flush
+#ifdef L_gcov_lock_unlock
#ifdef __GTHREAD_MUTEX_INIT
-__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT;
+__gthread_mutex_t __gcov_mx = __GTHREAD_MUTEX_INIT;
#define init_mx_once()
#else
-__gthread_mutex_t __gcov_flush_mx;
+__gthread_mutex_t __gcov_mx;
static void
init_mx (void)
{
- __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
+ __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx);
}
static void
@@ -74,23 +61,23 @@ init_mx_once (void)
}
#endif
-/* Called before fork or exec - write out profile information gathered so
- far and reset it to zero. This avoids duplication or loss of the
- profile information gathered so far. */
+/* Lock critical section for __gcov_dump and __gcov_reset functions. */
void
-__gcov_flush (void)
+__gcov_lock (void)
{
init_mx_once ();
- __gthread_mutex_lock (&__gcov_flush_mx);
+ __gthread_mutex_lock (&__gcov_mx);
+}
- __gcov_dump_int ();
- __gcov_reset_int ();
+/* Unlock critical section for __gcov_dump and __gcov_reset functions. */
- __gthread_mutex_unlock (&__gcov_flush_mx);
+void
+__gcov_unlock (void)
+{
+ __gthread_mutex_unlock (&__gcov_mx);
}
-
-#endif /* L_gcov_flush */
+#endif
#ifdef L_gcov_reset
@@ -143,7 +130,17 @@ __gcov_reset_int (void)
}
}
-ALIAS_void_fn (__gcov_reset_int, __gcov_reset);
+/* Exported function __gcov_reset. */
+
+void
+__gcov_reset (void)
+{
+ __gcov_lock ();
+
+ __gcov_reset_int ();
+
+ __gcov_unlock ();
+}
#endif /* L_gcov_reset */
@@ -163,22 +160,35 @@ __gcov_dump_int (void)
__gcov_dump_one (root);
}
-ALIAS_void_fn (__gcov_dump_int, __gcov_dump);
+/* Exported function __gcov_dump. */
+
+void
+__gcov_dump (void)
+{
+ __gcov_lock ();
+
+ __gcov_dump_int ();
+
+ __gcov_unlock ();
+}
#endif /* L_gcov_dump */
#ifdef L_gcov_fork
-/* A wrapper for the fork function. Flushes the accumulated profiling data, so
- that they are not counted twice. */
+/* A wrapper for the fork function. We reset counters in the child
+ so that they are not counted twice. */
pid_t
__gcov_fork (void)
{
pid_t pid;
- __gcov_flush ();
pid = fork ();
if (pid == 0)
- __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx);
+ {
+ __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx);
+ /* We do not need locking as we are the only thread in the child. */
+ __gcov_reset_int ();
+ }
return pid;
}
#endif
@@ -194,7 +204,8 @@ __gcov_execl (const char *path, char *arg, ...)
unsigned i, length;
char **args;
- __gcov_flush ();
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
va_start (ap, arg);
va_copy (aq, ap);
@@ -210,7 +221,10 @@ __gcov_execl (const char *path, char *arg, ...)
args[i] = va_arg (aq, char *);
va_end (aq);
- return execv (path, args);
+ int ret = execv (path, args);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
@@ -225,7 +239,8 @@ __gcov_execlp (const char *path, char *arg, ...)
unsigned i, length;
char **args;
- __gcov_flush ();
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
va_start (ap, arg);
va_copy (aq, ap);
@@ -241,7 +256,10 @@ __gcov_execlp (const char *path, char *arg, ...)
args[i] = va_arg (aq, char *);
va_end (aq);
- return execvp (path, args);
+ int ret = execvp (path, args);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
@@ -257,7 +275,8 @@ __gcov_execle (const char *path, char *arg, ...)
char **args;
char **envp;
- __gcov_flush ();
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
va_start (ap, arg);
va_copy (aq, ap);
@@ -274,7 +293,10 @@ __gcov_execle (const char *path, char *arg, ...)
envp = va_arg (aq, char **);
va_end (aq);
- return execve (path, args, envp);
+ int ret = execve (path, args, envp);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
@@ -285,8 +307,12 @@ __gcov_execle (const char *path, char *arg, ...)
int
__gcov_execv (const char *path, char *const argv[])
{
- __gcov_flush ();
- return execv (path, argv);
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
+ int ret = execv (path, argv);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
@@ -297,8 +323,12 @@ __gcov_execv (const char *path, char *const argv[])
int
__gcov_execvp (const char *path, char *const argv[])
{
- __gcov_flush ();
- return execvp (path, argv);
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
+ int ret = execvp (path, argv);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
@@ -309,8 +339,12 @@ __gcov_execvp (const char *path, char *const argv[])
int
__gcov_execve (const char *path, char *const argv[], char *const envp[])
{
- __gcov_flush ();
- return execve (path, argv, envp);
+ /* Dump counters only, they will be lost after exec. */
+ __gcov_dump ();
+ int ret = execve (path, argv, envp);
+ /* We reach this code only when execv fails, reset counter then here. */
+ __gcov_reset ();
+ return ret;
}
#endif
#endif /* inhibit_libc */
diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c
index c0785b0..1acdaa0 100644
--- a/libgcc/libgcov-merge.c
+++ b/libgcc/libgcov-merge.c
@@ -86,86 +86,6 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
#ifdef L_gcov_merge_topn
-/* To merging of TOPN profiles.
- counters[0] is the number of executions
- for i in 0 ... TOPN-1
- counters[2 * i + 1] is target
- counters[2 * i + 2] is corresponding hitrate counter.
-
- Because we prune counters only those with probability >= 1/TOPN are
- present now.
-
- We use sign of counters[0] to track whether the number of different
- targets exceeds TOPN. */
-
-static void
-merge_topn_values_set (gcov_type *counters)
-{
- /* First value is number of total executions of the profiler. */
- gcov_type all = gcov_get_counter ();
- gcov_type *total = &counters[0];
- ++counters;
-
- /* Negative value means that counter is missing some of values. */
- if (all < 0)
- *total = -(*total);
-
- *total += all;
-
- /* Read all part values. */
- gcov_type read_counters[2 * GCOV_TOPN_VALUES];
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- {
- read_counters[2 * i] = gcov_get_counter_target ();
- read_counters[2 * i + 1] = gcov_get_counter_ignore_scaling (-1);
- }
-
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- {
- if (read_counters[2 * i + 1] == 0)
- continue;
-
- unsigned j;
- int slot = 0;
-
- for (j = 0; j < GCOV_TOPN_VALUES; j++)
- {
- if (counters[2 * j] == read_counters[2 * i])
- {
- counters[2 * j + 1] += read_counters[2 * i + 1];
- break;
- }
- else if (counters[2 * j + 1] < counters[2 * slot + 1])
- slot = j;
- }
-
- if (j == GCOV_TOPN_VALUES)
- {
- gcov_type slot_count = counters[2 * slot + 1];
- /* We found an empty slot. */
- if (slot_count == 0)
- {
- /* If we found empty slot, add the value. */
- counters[2 * slot] = read_counters[2 * i];
- counters[2 * slot + 1] = read_counters[2 * i + 1];
- }
- else
- {
- /* Here we are loosing some values. */
- if (*total >= 0)
- *total = -(*total);
- if (read_counters[2 * i + 1] > slot_count)
- {
- counters[2 * slot] = read_counters[2 * i];
- counters[2 * slot + 1] = read_counters[2 * i + 1];
- }
- else
- counters[2 * slot + 1] -= read_counters[2 * i + 1];
- }
- }
- }
-}
-
/* The profile merging function for choosing the most common value.
It is given an array COUNTERS of N_COUNTERS old counters and it
reads the same number of counters from the gcov file. The counters
@@ -175,13 +95,30 @@ merge_topn_values_set (gcov_type *counters)
-- the stored candidate on the most common value of the measured entity
-- counter
*/
+
void
__gcov_merge_topn (gcov_type *counters, unsigned n_counters)
{
- gcc_assert (!(n_counters % GCOV_TOPN_VALUES_COUNTERS));
+ gcc_assert (!(n_counters % GCOV_TOPN_MEM_COUNTERS));
- for (unsigned i = 0; i < (n_counters / GCOV_TOPN_VALUES_COUNTERS); i++)
- merge_topn_values_set (counters + (i * GCOV_TOPN_VALUES_COUNTERS));
+ for (unsigned i = 0; i < (n_counters / GCOV_TOPN_MEM_COUNTERS); i++)
+ {
+ /* First value is number of total executions of the profiler. */
+ gcov_type all = gcov_get_counter_ignore_scaling (-1);
+ gcov_type n = gcov_get_counter_ignore_scaling (-1);
+
+ counters[GCOV_TOPN_MEM_COUNTERS * i] += all;
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ gcov_type value = gcov_get_counter_target ();
+ gcov_type count = gcov_get_counter_ignore_scaling (-1);
+
+ // TODO: we should use atomic here
+ gcov_topn_add_value (counters + GCOV_TOPN_MEM_COUNTERS * i, value,
+ count, 0, 0);
+ }
+ }
}
#endif /* L_gcov_merge_topn */
diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c
index 6043ac4..45ab93c 100644
--- a/libgcc/libgcov-profiler.c
+++ b/libgcc/libgcov-profiler.c
@@ -26,17 +26,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "libgcov.h"
#if !defined(inhibit_libc)
-/* Detect whether target can support atomic update of profilers. */
-#if __SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
-#define GCOV_SUPPORTS_ATOMIC 1
-#else
-#if __SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
-#define GCOV_SUPPORTS_ATOMIC 1
-#else
-#define GCOV_SUPPORTS_ATOMIC 0
-#endif
-#endif
-
#ifdef L_gcov_interval_profiler
/* If VALUE is in interval <START, START + STEPS - 1>, then increases the
corresponding counter in COUNTERS. If the VALUE is above or below
@@ -105,51 +94,13 @@ __gcov_pow2_profiler_atomic (gcov_type *counters, gcov_type value)
}
#endif
-
/* Tries to determine N most commons value among its inputs. */
static inline void
__gcov_topn_values_profiler_body (gcov_type *counters, gcov_type value,
int use_atomic)
{
- if (use_atomic)
- __atomic_fetch_add (&counters[0], 1, __ATOMIC_RELAXED);
- else
- counters[0]++;
-
- ++counters;
-
- /* First try to find an existing value. */
- int empty_counter = -1;
-
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- if (value == counters[2 * i])
- {
- if (use_atomic)
- __atomic_fetch_add (&counters[2 * i + 1], GCOV_TOPN_VALUES,
- __ATOMIC_RELAXED);
- else
- counters[2 * i + 1] += GCOV_TOPN_VALUES;
- return;
- }
- else if (counters[2 * i + 1] <= 0)
- empty_counter = i;
-
- /* Find an empty slot for a new value. */
- if (empty_counter != -1)
- {
- counters[2 * empty_counter] = value;
- counters[2 * empty_counter + 1] = GCOV_TOPN_VALUES;
- return;
- }
-
- /* We haven't found an empty slot, then decrement all
- counter values by one. */
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- if (use_atomic)
- __atomic_fetch_sub (&counters[2 * i + 1], 1, __ATOMIC_RELAXED);
- else
- counters[2 * i + 1]--;
+ gcov_topn_add_value (counters, value, 1, use_atomic, 1);
}
#ifdef L_gcov_topn_values_profiler
diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c
index 449638b..1ada1fe 100644
--- a/libgcc/libgcov-util.c
+++ b/libgcc/libgcov-util.c
@@ -57,12 +57,12 @@ void gcov_set_verbose (void)
#include <ftw.h>
#endif
-static void tag_function (unsigned, unsigned);
-static void tag_blocks (unsigned, unsigned);
-static void tag_arcs (unsigned, unsigned);
-static void tag_lines (unsigned, unsigned);
-static void tag_counters (unsigned, unsigned);
-static void tag_summary (unsigned, unsigned);
+static void tag_function (unsigned, int);
+static void tag_blocks (unsigned, int);
+static void tag_arcs (unsigned, int);
+static void tag_lines (unsigned, int);
+static void tag_counters (unsigned, int);
+static void tag_summary (unsigned, int);
/* The gcov_info for the first module. */
static struct gcov_info *curr_gcov_info;
@@ -80,8 +80,6 @@ static int k_ctrs_mask[GCOV_COUNTERS];
static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
/* Number of kind of counters that have been seen. */
static int k_ctrs_types;
-/* The object summary being processed. */
-static struct gcov_summary *curr_object_summary;
/* Merge functions for counters. */
#define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
@@ -119,7 +117,7 @@ typedef struct tag_format
{
unsigned tag;
char const *name;
- void (*proc) (unsigned, unsigned);
+ void (*proc) (unsigned, int);
} tag_format_t;
/* Handler table for various Tags. */
@@ -140,7 +138,7 @@ static const tag_format_t tag_table[] =
/* Handler for reading function tag. */
static void
-tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+tag_function (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
{
int i;
@@ -173,7 +171,7 @@ tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
/* Handler for reading block tag. */
static void
-tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+tag_blocks (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
{
/* TBD: gcov-tool currently does not handle gcno files. Assert here. */
gcc_unreachable ();
@@ -182,7 +180,7 @@ tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
/* Handler for reading flow arc tag. */
static void
-tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+tag_arcs (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
{
/* TBD: gcov-tool currently does not handle gcno files. Assert here. */
gcc_unreachable ();
@@ -191,7 +189,7 @@ tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
/* Handler for reading line tag. */
static void
-tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+tag_lines (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED)
{
/* TBD: gcov-tool currently does not handle gcno files. Assert here. */
gcc_unreachable ();
@@ -200,9 +198,9 @@ tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
/* Handler for reading counters array tag with value as TAG and length of LENGTH. */
static void
-tag_counters (unsigned tag, unsigned length)
+tag_counters (unsigned tag, int length)
{
- unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
+ unsigned n_counts = GCOV_TAG_COUNTER_NUM (abs (length));
gcov_type *values;
unsigned ix;
unsigned tag_ix;
@@ -213,20 +211,21 @@ tag_counters (unsigned tag, unsigned length)
gcc_assert (k_ctrs[tag_ix].num == 0);
k_ctrs[tag_ix].num = n_counts;
- k_ctrs[tag_ix].values = values = (gcov_type *) xmalloc (n_counts * sizeof (gcov_type));
+ k_ctrs[tag_ix].values = values = (gcov_type *) xcalloc (sizeof (gcov_type),
+ n_counts);
gcc_assert (values);
- for (ix = 0; ix != n_counts; ix++)
- values[ix] = gcov_read_counter ();
+ if (length > 0)
+ for (ix = 0; ix != n_counts; ix++)
+ values[ix] = gcov_read_counter ();
}
/* Handler for reading summary tag. */
static void
-tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
+tag_summary (unsigned tag ATTRIBUTE_UNUSED, int ATTRIBUTE_UNUSED)
{
- curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1);
- gcov_read_summary (curr_object_summary);
+ gcov_read_summary (&curr_gcov_info->summary);
}
/* This function is called at the end of reading a gcda file.
@@ -243,7 +242,7 @@ read_gcda_finalize (struct gcov_info *obj_info)
/* We set the following fields: merge, n_functions, functions
and summary. */
obj_info->n_functions = num_fn_info;
- obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info);
+ obj_info->functions = (struct gcov_fn_info**) obstack_finish (&fn_info);
/* wrap all the counter array. */
for (i=0; i< GCOV_COUNTERS; i++)
@@ -261,7 +260,7 @@ read_gcda_file (const char *filename)
{
unsigned tags[4];
unsigned depth = 0;
- unsigned magic, version;
+ unsigned version;
struct gcov_info *obj_info;
int i;
@@ -276,8 +275,7 @@ read_gcda_file (const char *filename)
}
/* Read magic. */
- magic = gcov_read_unsigned ();
- if (magic != GCOV_DATA_MAGIC)
+ if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC))
{
fnotice (stderr, "%s:not a gcov data file\n", filename);
gcov_close ();
@@ -301,7 +299,6 @@ read_gcda_file (const char *filename)
obstack_init (&fn_info);
num_fn_info = 0;
curr_fn_info = 0;
- curr_object_summary = NULL;
{
size_t len = strlen (filename) + 1;
char *str_dup = (char*) xmalloc (len);
@@ -325,7 +322,8 @@ read_gcda_file (const char *filename)
tag = gcov_read_unsigned ();
if (!tag)
break;
- length = gcov_read_unsigned ();
+ int read_length = (int)gcov_read_unsigned ();
+ length = read_length > 0 ? read_length : 0;
base = gcov_position ();
mask = GCOV_TAG_MASK (tag) >> 1;
for (tag_depth = 4; mask; mask >>= 8)
@@ -358,7 +356,7 @@ read_gcda_file (const char *filename)
{
unsigned long actual_length;
- (*format->proc) (tag, length);
+ (*format->proc) (tag, read_length);
actual_length = gcov_position () - base;
if (actual_length > length)
@@ -507,14 +505,58 @@ gcov_get_merge_weight (void)
value buffer and weights and then calls the merge function. */
static void
-merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n,
- gcov_type *v2, unsigned w)
+merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n1,
+ gcov_type *v2, gcov_unsigned_t n2, unsigned w)
{
gcov_value_buf = v2;
gcov_value_buf_pos = 0;
- gcov_value_buf_size = n;
+ gcov_value_buf_size = n2;
gcov_merge_weight = w;
- (*f) (v1, n);
+ (*f) (v1, n1);
+}
+
+/* Convert on disk representation of a TOPN counter to in memory representation
+ that is expected from __gcov_merge_topn function. */
+
+static void
+topn_to_memory_representation (struct gcov_ctr_info *info)
+{
+ auto_vec<gcov_type> output;
+ gcov_type *values = info->values;
+ int count = info->num;
+
+ while (count > 0)
+ {
+ output.safe_push (values[0]);
+ gcov_type n = values[1];
+ output.safe_push (n);
+ if (n > 0)
+ {
+ struct gcov_kvp *tuples
+ = (struct gcov_kvp *)xcalloc (sizeof (struct gcov_kvp), n);
+ for (unsigned i = 0; i < n - 1; i++)
+ tuples[i].next = &tuples[i + 1];
+ for (unsigned i = 0; i < n; i++)
+ {
+ tuples[i].value = values[2 + 2 * i];
+ tuples[i].count = values[2 + 2 * i + 1];
+ }
+ output.safe_push ((intptr_t)&tuples[0]);
+ }
+ else
+ output.safe_push (0);
+
+ unsigned len = 2 * n + 2;
+ values += len;
+ count -= len;
+ }
+ gcc_assert (count == 0);
+
+ /* Allocate new buffer and copy it there. */
+ info->num = output.length ();
+ info->values = (gcov_type *)xmalloc (sizeof (gcov_type) * info->num);
+ for (unsigned i = 0; i < info->num; i++)
+ info->values[i] = output[i];
}
/* Offline tool to manipulate profile data.
@@ -541,12 +583,17 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
int has_mismatch = 0;
gcc_assert (info2->n_functions == n_functions);
+
+ /* Merge summary. */
+ info1->summary.runs += info2->summary.runs;
+ info1->summary.sum_max += info2->summary.sum_max;
+
for (f_ix = 0; f_ix < n_functions; f_ix++)
{
unsigned t_ix;
- const struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
- const struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
- const struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
+ struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix];
+ struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix];
+ struct gcov_ctr_info *ci_ptr1, *ci_ptr2;
if (!gfi_ptr1 || gfi_ptr1->key != info1)
continue;
@@ -570,8 +617,14 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w)
gcc_assert (merge1 == merge2);
if (!merge1)
continue;
- gcc_assert (ci_ptr1->num == ci_ptr2->num);
- merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, ci_ptr2->values, w);
+
+ if (merge1 == __gcov_merge_topn)
+ topn_to_memory_representation (ci_ptr1);
+ else
+ gcc_assert (ci_ptr1->num == ci_ptr2->num);
+
+ merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num,
+ ci_ptr2->values, ci_ptr2->num, w);
ci_ptr1++;
ci_ptr2++;
}
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 023293e..8be5beb 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -85,6 +85,19 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI)));
#define GCOV_LOCKED 0
#endif
+#ifndef GCOV_SUPPORTS_ATOMIC
+/* Detect whether target can support atomic update of profilers. */
+#if __SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+#define GCOV_SUPPORTS_ATOMIC 1
+#else
+#if __SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+#define GCOV_SUPPORTS_ATOMIC 1
+#else
+#define GCOV_SUPPORTS_ATOMIC 0
+#endif
+#endif
+#endif
+
/* In libgcov we need these functions to be extern, so prefix them with
__gcov. In libgcov they must also be hidden so that the instance in
the executable is not also used in a DSO. */
@@ -147,7 +160,7 @@ extern struct gcov_info *gcov_list;
/* Poison these, so they don't accidentally slip in. */
#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length
-#pragma GCC poison gcov_time gcov_magic
+#pragma GCC poison gcov_time
#ifdef HAVE_GAS_HIDDEN
#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
@@ -203,7 +216,8 @@ struct gcov_info
const struct gcov_fn_info *const *functions; /* pointer to pointers
to function information */
#else
- const struct gcov_fn_info **functions;
+ struct gcov_fn_info **functions;
+ struct gcov_summary summary;
#endif /* !IN_GCOV_TOOL */
};
@@ -236,6 +250,8 @@ struct indirect_call_tuple
/* Exactly one of these will be active in the process. */
extern struct gcov_master __gcov_master;
+extern struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP];
+extern unsigned __gcov_kvp_pool_index;
/* Dump a set of gcov objects. */
extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
@@ -253,6 +269,12 @@ extern void __gcov_reset_int (void) ATTRIBUTE_HIDDEN;
/* User function to enable early write of profile information so far. */
extern void __gcov_dump_int (void) ATTRIBUTE_HIDDEN;
+/* Lock critical section for __gcov_dump and __gcov_reset functions. */
+extern void __gcov_lock (void) ATTRIBUTE_HIDDEN;
+
+/* Unlock critical section for __gcov_dump and __gcov_reset functions. */
+extern void __gcov_unlock (void) ATTRIBUTE_HIDDEN;
+
/* The merge function that just sums the counters. */
extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN;
@@ -367,6 +389,146 @@ gcov_get_counter_target (void)
#endif
}
+/* Add VALUE to *COUNTER and make it with atomic operation
+ if USE_ATOMIC is true. */
+
+static inline void
+gcov_counter_add (gcov_type *counter, gcov_type value,
+ int use_atomic ATTRIBUTE_UNUSED)
+{
+#if GCOV_SUPPORTS_ATOMIC
+ if (use_atomic)
+ __atomic_fetch_add (counter, value, __ATOMIC_RELAXED);
+ else
+#endif
+ *counter += value;
+}
+
+/* Allocate gcov_kvp from heap. If we are recursively called, then allocate
+ it from a list of pre-allocated pool. */
+
+static inline struct gcov_kvp *
+allocate_gcov_kvp (void)
+{
+ struct gcov_kvp *new_node = NULL;
+
+ static
+#if defined(HAVE_CC_TLS)
+__thread
+#endif
+ volatile unsigned in_recursion ATTRIBUTE_UNUSED = 0;
+
+#if !defined(IN_GCOV_TOOL) && !defined(L_gcov_merge_topn)
+ if (__builtin_expect (in_recursion, 0))
+ {
+ unsigned index;
+#if GCOV_SUPPORTS_ATOMIC
+ index
+ = __atomic_fetch_add (&__gcov_kvp_pool_index, 1, __ATOMIC_RELAXED);
+#else
+ index = __gcov_kvp_pool_index++;
+#endif
+ if (index < GCOV_PREALLOCATED_KVP)
+ new_node = &__gcov_kvp_pool[index];
+ else
+ /* Do not crash in the situation. */
+ return NULL;
+ }
+ else
+#endif
+ {
+ in_recursion = 1;
+ new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
+ in_recursion = 0;
+ }
+
+ return new_node;
+}
+
+/* Add key value pair VALUE:COUNT to a top N COUNTERS. When INCREMENT_TOTAL
+ is true, add COUNT to total of the TOP counter. If USE_ATOMIC is true,
+ do it in atomic way. */
+
+static inline void
+gcov_topn_add_value (gcov_type *counters, gcov_type value, gcov_type count,
+ int use_atomic, int increment_total)
+{
+ if (increment_total)
+ gcov_counter_add (&counters[0], 1, use_atomic);
+
+ struct gcov_kvp *prev_node = NULL;
+ struct gcov_kvp *minimal_node = NULL;
+ struct gcov_kvp *current_node = (struct gcov_kvp *)(intptr_t)counters[2];
+
+ while (current_node)
+ {
+ if (current_node->value == value)
+ {
+ gcov_counter_add (&current_node->count, count, use_atomic);
+ return;
+ }
+
+ if (minimal_node == NULL
+ || current_node->count < minimal_node->count)
+ minimal_node = current_node;
+
+ prev_node = current_node;
+ current_node = current_node->next;
+ }
+
+ if (counters[1] == GCOV_TOPN_MAXIMUM_TRACKED_VALUES)
+ {
+ if (--minimal_node->count < count)
+ {
+ minimal_node->value = value;
+ minimal_node->count = count;
+ }
+ }
+ else
+ {
+ struct gcov_kvp *new_node = allocate_gcov_kvp ();
+ if (new_node == NULL)
+ return;
+
+ new_node->value = value;
+ new_node->count = count;
+
+ int success = 0;
+ if (!counters[2])
+ {
+#if GCOV_SUPPORTS_ATOMIC
+ if (use_atomic)
+ {
+ struct gcov_kvp **ptr = (struct gcov_kvp **)(intptr_t)&counters[2];
+ success = !__sync_val_compare_and_swap (ptr, 0, new_node);
+ }
+ else
+#endif
+ {
+ counters[2] = (intptr_t)new_node;
+ success = 1;
+ }
+ }
+ else if (prev_node && !prev_node->next)
+ {
+#if GCOV_SUPPORTS_ATOMIC
+ if (use_atomic)
+ success = !__sync_val_compare_and_swap (&prev_node->next, 0,
+ new_node);
+ else
+#endif
+ {
+ prev_node->next = new_node;
+ success = 1;
+ }
+ }
+
+ /* Increment number of nodes. */
+ if (success)
+ gcov_counter_add (&counters[1], 1, use_atomic);
+ }
+}
+
#endif /* !inhibit_libc */
#endif /* GCC_LIBGCOV_H */
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 62d4a3d..fe89656 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -1538,11 +1538,14 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
/* Compute the return address now, since the return address column
can change from frame to frame. */
- context->ra = __builtin_extract_return_addr
- (_Unwind_GetPtr (context, fs->retaddr_column));
-#ifdef MD_POST_EXTRACT_FRAME_ADDR
- context->ra = MD_POST_EXTRACT_FRAME_ADDR (context, fs, context->ra);
+ void *ret_addr;
+#ifdef MD_DEMANGLE_RETURN_ADDR
+ _Unwind_Word ra = _Unwind_GetGR (context, fs->retaddr_column);
+ ret_addr = MD_DEMANGLE_RETURN_ADDR (context, fs, ra);
+#else
+ ret_addr = _Unwind_GetPtr (context, fs->retaddr_column);
#endif
+ context->ra = __builtin_extract_return_addr (ret_addr);
}
}
@@ -1577,9 +1580,6 @@ uw_init_context_1 (struct _Unwind_Context *context,
void *outer_cfa, void *outer_ra)
{
void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
-#ifdef MD_POST_EXTRACT_ROOT_ADDR
- ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
-#endif
_Unwind_FrameState fs;
_Unwind_SpTmp sp_slot;
_Unwind_Reason_Code code;
@@ -1616,9 +1616,6 @@ uw_init_context_1 (struct _Unwind_Context *context,
initialization context, then we can't see it in the given
call frame data. So have the initialization context tell us. */
context->ra = __builtin_extract_return_addr (outer_ra);
-#ifdef MD_POST_EXTRACT_ROOT_ADDR
- context->ra = MD_POST_EXTRACT_ROOT_ADDR (context->ra);
-#endif
}
static void _Unwind_DebugHook (void *, void *)
@@ -1641,21 +1638,6 @@ _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
#endif
}
-/* Frob exception handler's address kept in TARGET before installing into
- CURRENT context. */
-
-static inline void *
-uw_frob_return_addr (struct _Unwind_Context *current
- __attribute__ ((__unused__)),
- struct _Unwind_Context *target)
-{
- void *ret_addr = __builtin_frob_return_addr (target->ra);
-#ifdef MD_POST_FROB_EH_HANDLER_ADDR
- ret_addr = MD_POST_FROB_EH_HANDLER_ADDR (current, target, ret_addr);
-#endif
- return ret_addr;
-}
-
/* Install TARGET into CURRENT so that we can return to it. This is a
macro because __builtin_eh_return must be invoked in the context of
our caller. FRAMES is a number of frames to be unwind.
@@ -1667,7 +1649,7 @@ uw_frob_return_addr (struct _Unwind_Context *current
do \
{ \
long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
- void *handler = uw_frob_return_addr ((CURRENT), (TARGET)); \
+ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
_Unwind_DebugHook ((TARGET)->cfa, handler); \
_Unwind_Frames_Extra (FRAMES); \
__builtin_eh_return (offset, handler); \