aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-07-11 12:43:49 -0700
committerIan Lance Taylor <iant@golang.org>2020-07-11 12:43:49 -0700
commit4854d721be78358e59367982bdd94461b4be3c5a (patch)
tree8ead189e618f8ef1456c8b02c81de0cc1585d8a6 /libgcc
parent3cdc95b9f8d6c90c4a279783fd3da961c5afb22c (diff)
parente109f6e438b72ef3e403162971068d28d09b82f5 (diff)
downloadgcc-4854d721be78358e59367982bdd94461b4be3c5a.zip
gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.gz
gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.bz2
Merge from trunk revision e109f6e438b72ef3e403162971068d28d09b82f5
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog292
-rw-r--r--libgcc/Makefile.in27
-rw-r--r--libgcc/config.host19
-rw-r--r--libgcc/config.in3
-rw-r--r--libgcc/config/aarch64/aarch64-unwind.h2
-rw-r--r--libgcc/config/aarch64/lse-init.c17
-rw-r--r--libgcc/config/aarch64/lse.S87
-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/sfp-exceptions.c42
-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/riscv/div.S8
-rw-r--r--libgcc/config/rs6000/crtresfpr.S1
-rw-r--r--libgcc/config/rs6000/crtresxfpr.S1
-rw-r--r--libgcc/config/rs6000/crtsavfpr.S1
-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/configure72
-rw-r--r--libgcc/configure.ac33
-rw-r--r--libgcc/empty.mk2
-rw-r--r--libgcc/gcov.h5
-rw-r--r--libgcc/libgcov-driver.c172
-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.h121
37 files changed, 1137 insertions, 1059 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 6340cfb..602c907 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,295 @@
+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 evaluate
+ generic division to generate INVALID and DIVZERO exceptions.
+
+2020-04-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config/rs6000/crtresfpr.S: Use .machine ppc.
+ * config/rs6000/crtresxfpr.S: Likewise.
+ * config/rs6000/crtsavfpr.S: Likewise.
+
+2020-04-21 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ PR target/94514
+ * config/aarch64/aarch64-unwind.h (aarch64_frob_update_context):
+ Update context->flags accroding to the frame state.
+
+2020-04-19 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sfp-exceptions.c (__sfp_handle_exceptions) [__SSE_MATH__]:
+ Remove unneeded assignments to volatile memory.
+
+2020-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/93053
+ * configure.ac (LIBGCC_CHECK_AS_LSE): Add HAVE_AS_LSE checking.
+ * config/aarch64/lse.S: Include auto-target.h, if HAVE_AS_LSE
+ is not defined, use just .arch armv8-a.
+ (B, M, N, OPN): Define.
+ (COMMENT): New .macro.
+ (CAS, CASP, SWP, LDOP): Use .inst directive if HAVE_AS_LSE is not
+ defined. Otherwise, move the operands right after the glue? and
+ comment out operands where the macros are used.
+ * configure: Regenerated.
+ * config.in: Regenerated.
+
2020-04-07 Ian Lance Taylor <iant@golang.org>
PR libgcc/94513
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 851e765..d6075d3 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.in b/libgcc/config.in
index 59a3d8d..5be5321 100644
--- a/libgcc/config.in
+++ b/libgcc/config.in
@@ -10,6 +10,9 @@
*/
#undef HAVE_AS_CFI_SECTIONS
+/* Define to 1 if the assembler supports LSE. */
+#undef HAVE_AS_LSE
+
/* Define to 1 if the target assembler supports thread-local storage. */
#undef HAVE_CC_TLS
diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
index 4c8790b..ed84a96 100644
--- a/libgcc/config/aarch64/aarch64-unwind.h
+++ b/libgcc/config/aarch64/aarch64-unwind.h
@@ -104,6 +104,8 @@ aarch64_frob_update_context (struct _Unwind_Context *context,
if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
/* The flag is used for re-authenticating EH handler's address. */
context->flags |= RA_SIGNED_BIT;
+ else
+ context->flags &= ~RA_SIGNED_BIT;
return;
}
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 ca6495f..64691c6 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -48,8 +48,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
* separately to minimize code size.
*/
+#include "auto-target.h"
+
/* Tell the assembler to accept LSE instructions. */
+#ifdef HAVE_AS_LSE
.arch armv8-a+lse
+#else
+ .arch armv8-a
+#endif
/* Declare the symbol gating the LSE implementations. */
.hidden __aarch64_have_lse_atomics
@@ -58,12 +64,19 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#if SIZE == 1
# define S b
# define UXT uxtb
+# define B 0x00000000
#elif SIZE == 2
# define S h
# define UXT uxth
+# define B 0x40000000
#elif SIZE == 4 || SIZE == 8 || SIZE == 16
# define S
# define UXT mov
+# if SIZE == 4
+# define B 0x80000000
+# elif SIZE == 8
+# define B 0xc0000000
+# endif
#else
# error
#endif
@@ -72,18 +85,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# define SUFF _relax
# define A
# define L
+# define M 0x000000
+# define N 0x000000
#elif MODEL == 2
# define SUFF _acq
# define A a
# define L
+# define M 0x400000
+# define N 0x800000
#elif MODEL == 3
# define SUFF _rel
# define A
# define L l
+# define M 0x008000
+# define N 0x400000
#elif MODEL == 4
# define SUFF _acq_rel
# define A a
# define L l
+# define M 0x408000
+# define N 0xc00000
#else
# error
#endif
@@ -115,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
@@ -124,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
@@ -144,9 +168,13 @@ STARTFN NAME(cas)
JUMP_IF_NOT_LSE 8f
#if SIZE < 16
-#define CAS glue4(cas, A, L, S)
+#ifdef HAVE_AS_LSE
+# define CAS glue4(cas, A, L, S) s(0), s(1), [x2]
+#else
+# define CAS .inst 0x08a07c41 + B + M
+#endif
- CAS s(0), s(1), [x2]
+ CAS /* s(0), s(1), [x2] */
ret
8: UXT s(tmp0), s(0)
@@ -160,9 +188,13 @@ STARTFN NAME(cas)
#else
#define LDXP glue3(ld, A, xp)
#define STXP glue3(st, L, xp)
-#define CASP glue3(casp, A, L)
+#ifdef HAVE_AS_LSE
+# define CASP glue3(casp, A, L) x0, x1, x2, x3, [x4]
+#else
+# define CASP .inst 0x48207c82 + M
+#endif
- CASP x0, x1, x2, x3, [x4]
+ CASP /* x0, x1, x2, x3, [x4] */
ret
8: mov x(tmp0), x0
@@ -181,12 +213,16 @@ ENDFN NAME(cas)
#endif
#ifdef L_swp
-#define SWP glue4(swp, A, L, S)
+#ifdef HAVE_AS_LSE
+# define SWP glue4(swp, A, L, S) s(0), s(0), [x1]
+#else
+# define SWP .inst 0x38208020 + B + N
+#endif
STARTFN NAME(swp)
JUMP_IF_NOT_LSE 8f
- SWP s(0), s(0), [x1]
+ SWP /* s(0), s(0), [x1] */
ret
8: mov s(tmp0), s(0)
@@ -204,24 +240,32 @@ ENDFN NAME(swp)
#ifdef L_ldadd
#define LDNM ldadd
#define OP add
+#define OPN 0x0000
#elif defined(L_ldclr)
#define LDNM ldclr
#define OP bic
+#define OPN 0x1000
#elif defined(L_ldeor)
#define LDNM ldeor
#define OP eor
+#define OPN 0x2000
#elif defined(L_ldset)
#define LDNM ldset
#define OP orr
+#define OPN 0x3000
#else
#error
#endif
-#define LDOP glue4(LDNM, A, L, S)
+#ifdef HAVE_AS_LSE
+# define LDOP glue4(LDNM, A, L, S) s(0), s(0), [x1]
+#else
+# define LDOP .inst 0x38200020 + OPN + B + N
+#endif
STARTFN NAME(LDNM)
JUMP_IF_NOT_LSE 8f
- LDOP s(0), s(0), [x1]
+ LDOP /* s(0), s(0), [x1] */
ret
8: mov s(tmp0), s(0)
@@ -233,3 +277,30 @@ 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
+
+/* 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. */
+# ifdef __ARM_FEATURE_BTI_DEFAULT
+GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI)
+# 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/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c
index c994491..3aed0af 100644
--- a/libgcc/config/i386/sfp-exceptions.c
+++ b/libgcc/config/i386/sfp-exceptions.c
@@ -39,26 +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_div(x, y) \
+ do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0)
+#else
+# 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;
-#ifdef __SSE_MATH__
- volatile float r __attribute__ ((unused));
- asm volatile ("%vdivss\t{%0, %d0|%d0, %0}" : "+x" (f));
- r = f; /* Needed to trigger exception. */
-#else
- asm volatile ("fdiv\t{%y0, %0|%0, %y0}" : "+t" (f));
- /* No need for fwait, exception is triggered by emitted fstp. */
-#endif
+ __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));
@@ -67,18 +69,10 @@ __sfp_handle_exceptions (int _fex)
if (_fex & FP_EX_DIVZERO)
{
float f = 1.0f, g = 0.0f;
-#ifdef __SSE_MATH__
- volatile float r __attribute__ ((unused));
- asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
- r = f; /* Needed to trigger exception. */
-#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);
}
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));
@@ -86,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));
@@ -95,14 +88,7 @@ __sfp_handle_exceptions (int _fex)
if (_fex & FP_EX_INEXACT)
{
float f = 1.0f, g = 3.0f;
-#ifdef __SSE_MATH__
- volatile float r __attribute__ ((unused));
- asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g));
- r = f; /* Needed to trigger exception. */
-#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/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/rs6000/crtresfpr.S b/libgcc/config/rs6000/crtresfpr.S
index 6c0d01b..99e6f08 100644
--- a/libgcc/config/rs6000/crtresfpr.S
+++ b/libgcc/config/rs6000/crtresfpr.S
@@ -27,6 +27,7 @@
/* Do any initializations needed for the eabi environment */
+ .machine ppc
.section ".text"
#include "ppc-asm.h"
diff --git a/libgcc/config/rs6000/crtresxfpr.S b/libgcc/config/rs6000/crtresxfpr.S
index 9f01fa5..9931db2 100644
--- a/libgcc/config/rs6000/crtresxfpr.S
+++ b/libgcc/config/rs6000/crtresxfpr.S
@@ -27,6 +27,7 @@
/* Do any initializations needed for the eabi environment */
+ .machine ppc
.section ".text"
#include "ppc-asm.h"
diff --git a/libgcc/config/rs6000/crtsavfpr.S b/libgcc/config/rs6000/crtsavfpr.S
index fa043dd..dd8743a 100644
--- a/libgcc/config/rs6000/crtsavfpr.S
+++ b/libgcc/config/rs6000/crtsavfpr.S
@@ -27,6 +27,7 @@
/* Do any initializations needed for the eabi environment */
+ .machine ppc
.section ".text"
#include "ppc-asm.h"
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..e5f8a02 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 "`ar -X64 t libgcc_s.a`" ; 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 093036a..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
@@ -5530,6 +5532,46 @@ $as_echo "#define HAVE_AS_AVX 1" >>confdefs.h
;;
esac
+
+
+case "${target}" in
+aarch64*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports LSE" >&5
+$as_echo_n "checking if the assembler supports LSE... " >&6; }
+if ${libgcc_cv_as_lse+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+ asm(".arch armv8-a+lse\n\tcas w0, w1, [x2]");
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgcc_cv_as_lse=yes
+else
+ libgcc_cv_as_lse=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_as_lse" >&5
+$as_echo "$libgcc_cv_as_lse" >&6; }
+ if test x$libgcc_cv_as_lse = xyes; then
+
+$as_echo "#define HAVE_AS_LSE 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" >&5
$as_echo_n "checking for init priority support... " >&6; }
if ${libgcc_cv_init_priority+:} false; then :
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 85979da9..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
@@ -599,6 +597,25 @@ i[[34567]]86-*-* | x86_64-*-*)
esac])
LIBGCC_CHECK_AS_AVX
+dnl Check if as supports LSE instructions.
+AC_DEFUN([LIBGCC_CHECK_AS_LSE], [
+case "${target}" in
+aarch64*-*-*)
+ AC_CACHE_CHECK([if the assembler supports LSE], libgcc_cv_as_lse, [
+ AC_TRY_COMPILE([],
+changequote(,)dnl
+ asm(".arch armv8-a+lse\n\tcas w0, w1, [x2]");
+changequote([,])dnl
+ ,
+ [libgcc_cv_as_lse=yes], [libgcc_cv_as_lse=no])
+ ])
+ if test x$libgcc_cv_as_lse = xyes; then
+ AC_DEFINE(HAVE_AS_LSE, 1, [Define to 1 if the assembler supports LSE.])
+ fi
+ ;;
+esac])
+LIBGCC_CHECK_AS_LSE
+
dnl Check if as supports RTM instructions.
AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
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.c b/libgcc/libgcov-driver.c
index fb32073..2590593 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 */
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..81e1895 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 */
};
@@ -253,6 +267,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 +387,103 @@ 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;
+}
+
+/* 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
+ = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
+ 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 */