From f3201d7ce65a37fb1bc786cf24a743a59c149d22 Mon Sep 17 00:00:00 2001 From: Nobody Date: Thu, 11 Aug 2022 23:05:21 +0300 Subject: [PATCH] libgcc, libatomic, libquadmath with MCST patches --- builtin.h | 128 ++++ gcc_objdir/auto-host.h | 97 +++ gcc_objdir/gcov-iov.h | 4 + gcc_objdir/libgcc.mvars | 3 + gcc_objdir/tconfig.h | 10 + gcc_objdir/tm.h | 180 +++++ libatomic/Makefile.am | 2 +- libatomic/Makefile.in | 4 +- libatomic/configure | 12 +- libatomic/configure.ac | 2 +- libatomic/gcas.c | 16 + libatomic/gexch.c | 15 + libatomic/gload.c | 15 + libatomic/gstore.c | 12 + libatomic/libatomic_i.h | 9 + libgcc/Makefile.in | 18 +- libgcc/config.host | 12 +- libgcc/config/e2k/crtalign.S | 15 + libgcc/config/e2k/libgcc-glibc.ver | 64 ++ libgcc/config/e2k/sfp-exceptions.c | 32 + libgcc/config/e2k/sfp-machine.h | 100 +++ libgcc/config/e2k/t-crtalign | 2 + libgcc/config/e2k/t-eh-e2k | 6 + libgcc/config/e2k/t-linux | 3 + libgcc/config/e2k/t-softfp | 5 + libgcc/config/e2k/tf-signs.c | 71 ++ libgcc/config/e2k/unwind-dw2-e2k.c | 1127 ++++++++++++++++++++++++++++ libgcc/config/sparc/crtunaligned.c | 8 + libgcc/config/sparc/t-crtunaligned | 2 + libgcc/configure | 0 libgcc/crtstuff.c | 12 +- libgcc/libgcc-std.ver.in | 2 + libgcc/unwind-dw2-fde-dip.c | 317 +++++++- libgcc/unwind-dw2-fde.c | 147 +++- libgcc/unwind-dw2-fde.h | 39 +- libgcc/unwind-dw2.h | 3 + libgcc/unwind-generic.h | 31 +- libgcc/unwind-pe.h | 69 +- libgcc/unwind.inc | 63 +- libquadmath/configure | 4 +- libquadmath/printf/printf_fp.c | 432 +++++------ libtool.m4 | 8 +- 42 files changed, 2821 insertions(+), 280 deletions(-) create mode 100644 builtin.h create mode 100644 gcc_objdir/auto-host.h create mode 100644 gcc_objdir/gcov-iov.h create mode 100644 gcc_objdir/libgcc.mvars create mode 100644 gcc_objdir/tconfig.h create mode 100644 gcc_objdir/tm.h create mode 100644 libgcc/config/e2k/crtalign.S create mode 100644 libgcc/config/e2k/libgcc-glibc.ver create mode 100644 libgcc/config/e2k/sfp-exceptions.c create mode 100644 libgcc/config/e2k/sfp-machine.h create mode 100644 libgcc/config/e2k/t-crtalign create mode 100644 libgcc/config/e2k/t-eh-e2k create mode 100644 libgcc/config/e2k/t-linux create mode 100644 libgcc/config/e2k/t-softfp create mode 100644 libgcc/config/e2k/tf-signs.c create mode 100644 libgcc/config/e2k/unwind-dw2-e2k.c create mode 100644 libgcc/config/sparc/crtunaligned.c create mode 100644 libgcc/config/sparc/t-crtunaligned mode change 100644 => 100755 libgcc/configure diff --git a/builtin.h b/builtin.h new file mode 100644 index 00000000000..78a36168a95 --- /dev/null +++ b/builtin.h @@ -0,0 +1,128 @@ +/* Сюда пока в виде макросов + * Файл взял без изменений от такой же версии для gcc-3.4.6, поэтому + * комментарии соответствующие */ + +/* gnu'шный номер для регистра %sp */ +#define __builtin_dwarf_sp_column() 14 + +/* Инициализация массива char'ов размерами регистров. Нумерация идёт в gnu'той + * терминологии (см. файл mdes_sparc_reg.c, только там количество регистров + * не полное) */ +#ifdef __LP64__ +#define __builtin_init_dwarf_reg_size_table(buff) \ +{ \ + int i; \ + char *ptr = (char*)(buff); \ + for (i = 0; i < 32; i++) \ + ptr[i] = 8; \ + for (i = 33; i < 102; i++) \ + ptr[i] = 4; \ +} +#else +#define __builtin_init_dwarf_reg_size_table(buff) \ +{ \ + int i; \ + char *ptr = (char*)(buff); \ + for (i = 0; i < 102; i++) \ + ptr[i] = 4; \ +} +#endif + +/* Судя по всему, для sparc'а все регистры принудительно откачиваются в стек, + * потому как вся unwind-info описана в терминах того, что регистры + * от предыдущего окна хранятся в стеке + * + * Старый комментарий: + * + * Точно не заю что + * См. gcc-3.4.6/gcc/except.c процедура expand_builtin_unwind_init + * Далее на sparc'е вызывается gen_flush_register_windows, что соответсвует + * define_insn "flush_register_windows". При этом в процедуре + * expand_builtin_unwind_init взводится флажок current_function_has_nonlocal_label, + * по которому хз что делается, но, вроде бы как для -O0 некритично */ +#ifdef __LP64__ +#define __builtin_unwind_init() \ + asm ("flushw"); +#else +#define __builtin_unwind_init() \ + asm ("ta 3"); +#endif + +/* См. bug #82489 + * + * Старый комментарий: + * + * См. gcc-3.4.6/gcc/except.c процедура expand_builtin_eh_return_data_regno + * На sparc'е реализации такие: + * + * #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 24 : INVALID_REGNUM) + * DWARF_FRAME_REGNUM - не нашёл, но, судя по тому, что генерит sparc'овский gcc, + * он ничего не делает + * + * Параметр должен быть строго константный, но здесь нормально это не отсечём + * (чтобы была именно ошибка компиляции). Так что полагаем, что в исходниках + * у нас всё в порядке */ +#define __builtin_eh_return_data_regno(val) \ + (((val) >= 0 && (val) < 4) ? (val) + 24 : -1) + +/* Судя по всему, это вычисление CFA (Call Frame Adress). По сути описания + * в стандарте dwarf2 это есть значение %sp в предыдущем фрэйме (т.е. значение + * %fp в текущем фрэйме) + * + * Старый комментарий: + * + * Непонятно, что это, но на v9, судя по тому, что генерится, это + * результат '%fp + 2047', а на v8 просто '%fp'. + * Соответсвует return virtual_cfa_rtx; а откудо оно берётся - не осилил */ +#ifdef __LP64__ +#define __builtin_dwarf_cfa() \ + ({ void *p; \ + asm volatile ("add %%fp, 2047, %0" : "=r"(p)); \ + p; }) +#else +#define __builtin_dwarf_cfa() \ + ({ void *p; \ + asm volatile ("mov %%fp, %0" : "=r"(p)); \ + p; }) +#endif + +/* См. gcc-3.4.6/gcc/except.c процедура expand_builtin_frob_return_addr + * Фактически dst = src - RETURN_ADDR_OFFSET в терминах void* + * Для sparc'а + * #define RETURN_ADDR_OFFSET \ + * (8 + 4 * (! TARGET_ARCH64 && current_function_returns_struct)) + * Так что для режима 64 можно сделать и в виде макроса */ +#ifdef __LP64__ +#define __builtin_frob_return_addr(src) \ + ((void*)(src) - 8) +#else +/* В нашем случае нигде нет использования builtin'а в процедурах, возвращающих + * структуру, а потому реализуем вариант со скалярным результатом и нам пока + * этого достаточно. Полноценный вариант можно сделать только при поддержке + * builtin'а компилятором */ +#define __builtin_frob_return_addr(src) \ + ((void*)(src) - 8) +#endif + +/* См. gcc-3.4.6/gcc/except.c процедура expand_builtin_eh_return + * Мало чего понял, а потому сделал то, что делает gcc + * При этом есть подозрение, что использование %g1 и %g2 критично + * (по крайней мере про %g1 где-то что-то встречал) */ +#if defined __sparc__ +#define __builtin_eh_return(ival,ptr) \ + ({ \ + asm volatile ("mov %0, %%g1\n\t" \ + "mov %1, %%g2\n\t" \ + "mov %%g2, %%i7\n\t" \ + "restore\n\t" \ + "retl\n\t" \ + " add %%sp, %%g1, %%sp" \ + : : "r" ((long)(ival)), "r" ((void*)(ptr)) : "g1", "g2", "i7"); \ + }); +#elif defined __e2k__ +#define __builtin_eh_return(ival,ptr) \ + ({ \ + asm volatile ("nop" : : "r" ((long)(ival)), "r" ((void*)(ptr))); \ + }); + +#endif diff --git a/gcc_objdir/auto-host.h b/gcc_objdir/auto-host.h new file mode 100644 index 00000000000..eba314a8d5f --- /dev/null +++ b/gcc_objdir/auto-host.h @@ -0,0 +1,97 @@ +/* auto-host.h. Generated from config.in by configure. */ +/* config.in. Generated from configure.ac by autoheader. */ + +/* Define if you want runtime assertions enabled. This is a cheap check. */ +#define ENABLE_RUNTIME_CHECKING 1 + +/* Define 0/1 if your assembler supports CFI directives. */ +#define HAVE_GAS_CFI_DIRECTIVE 1 + +/* Define 0/1 if your assembler supports .cfi_personality. */ +#define HAVE_GAS_CFI_PERSONALITY_DIRECTIVE 1 + +/* Define 0/1 if your assembler supports .cfi_sections. */ +#define HAVE_GAS_CFI_SECTIONS_DIRECTIVE 1 + +/* Define if your assembler and linker support .hidden. */ +#define HAVE_GAS_HIDDEN 1 + +/* Define .init_array/.fini_array sections are available and working. */ +#ifndef USED_FOR_TARGET +/* __LCC_INITFINI_ARRAY__ , + * .init_array/.fini_array. + * , + * -print-mode=initfini. , + * , , + * libgcc libgcc.mcst. .. libgcc + * (, ) + * , . + * ݣ , , + * - ( + * solaris) . */ +# if ! defined __linux__ && ! defined __QNX__ +# error " HAVE_INITFINI_ARRAY_SUPPORT" +# endif +# if 1 /* defined __LCC_INITFINI_ARRAY__ */ +# define HAVE_INITFINI_ARRAY_SUPPORT 1 +# else /* ! defined __LCC_INITFINI_ARRAY__ */ +/* #undef HAVE_INITFINI_ARRAY_SUPPORT */ +# endif /* ! defined __LCC_INITFINI_ARRAY__ */ +#endif + + +/* Define if your linker supports .eh_frame_hdr. */ +#define HAVE_LD_EH_FRAME_HDR 1 + +/* Define if your target C library provides sys/sdt.h */ +/* #undef HAVE_SYS_SDT_H */ + +/* Define if your target C library provides the `dl_iterate_phdr' function. */ +/* #undef TARGET_DL_ITERATE_PHDR */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# define WORDS_BIGENDIAN 1 +# endif +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#ifndef USED_FOR_TARGET +#define _FILE_OFFSET_BITS 64 +#endif + + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + diff --git a/gcc_objdir/gcov-iov.h b/gcc_objdir/gcov-iov.h new file mode 100644 index 00000000000..ab38aecbe9d --- /dev/null +++ b/gcc_objdir/gcov-iov.h @@ -0,0 +1,4 @@ +/* Generated automatically by the program `build/gcov-iov' + from `7.3.0 (7 3) and (*)'. */ + +#define GCOV_VERSION ((gcov_unsigned_t)0x3730332a) /* 505* */ diff --git a/gcc_objdir/libgcc.mvars b/gcc_objdir/libgcc.mvars new file mode 100644 index 00000000000..210425626bb --- /dev/null +++ b/gcc_objdir/libgcc.mvars @@ -0,0 +1,3 @@ +GCC_CFLAGS = -DIN_GCC -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -isystem ./include +INHIBIT_LIBC_CFLAGS = +TARGET_SYSTEM_ROOT = diff --git a/gcc_objdir/tconfig.h b/gcc_objdir/tconfig.h new file mode 100644 index 00000000000..7ec80a1081a --- /dev/null +++ b/gcc_objdir/tconfig.h @@ -0,0 +1,10 @@ +#ifndef GCC_TCONFIG_H +#define GCC_TCONFIG_H +#ifndef USED_FOR_TARGET +# define USED_FOR_TARGET +#endif +#include "auto-host.h" +#ifdef IN_GCC +# include "ansidecl.h" +#endif +#endif /* GCC_TCONFIG_H */ diff --git a/gcc_objdir/tm.h b/gcc_objdir/tm.h new file mode 100644 index 00000000000..807920b4073 --- /dev/null +++ b/gcc_objdir/tm.h @@ -0,0 +1,180 @@ +#ifndef GCC_TM_H +#define GCC_TM_H + +/* ************************************************************************** */ + +/* - . */ + +#if defined(__sparc__) + +#if defined(__sparcv9) || defined(__arch64__) +#define UNITS_PER_WORD 8 +#else /* defined(__sparcv9) || defined(__arch64__) */ +#define UNITS_PER_WORD 4 +#endif /* defined(__sparcv9) || defined(__arch64__) */ + +#define MIN_UNITS_PER_WORD UNITS_PER_WORD + +/* FIXME , , , , e2k. */ +#define WIDEST_HARDWARE_FP_SIZE 64 + +/* DWARF_FRAME_REGISTERS. */ +#define FIRST_PSEUDO_REGISTER 103 + +/* __LIBGCC_STACK_GROWS_DOWNWARD__. */ +#define STACK_GROWS_DOWNWARD 1 + +/* __LIBGCC_EH_RETURN_STACKADJ_RTX__. */ +#define EH_RETURN_STACKADJ_RTX /* */ + +#define TEXT_SECTION_ASM_OP "\t.text" +#define INIT_SECTION_ASM_OP "\t.section \".init\"" +#define FINI_SECTION_ASM_OP "\t.section \".fini\"" + +/* ģ crtstuff.c, + * ( ). */ +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ +asm(SECTION_OP "\n" \ + "\tcall " #FUNC "\n" \ + "\t nop"); + +#elif defined(__e2k__) + +/* libgcc2.c, libgcc2.h MIN_UNITS_PER_WORD. */ +#define UNITS_PER_WORD 8 + +/* libgcc2.c, libgcc2.h. */ +#define MIN_UNITS_PER_WORD UNITS_PER_WORD + +/* DWARF_FRAME_REGISTERS. */ +/* FIXME , e2k. */ +#define FIRST_PSEUDO_REGISTER 48 + +#define TEXT_SECTION_ASM_OP "\t.text" +#define INIT_SECTION_ASM_OP "\t.section \".init\", \"ax\", @progbits" +#define FINI_SECTION_ASM_OP "\t.section \".fini\", \"ax\", @progbits" + +/* , wbs = 0x6. , crti.c + * ( ģ glibc). . */ +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ +asm(SECTION_OP "\n" \ + "\t{ nop 4; disp %ctpr1, " #FUNC " }\n" \ + "\tcall %ctpr1, wbs = 0x6\n"); + +#endif /* defined(__sparc__) || defined(__e2k__) */ + +/* ************************************************************************** */ + +/* . */ + +/* crtstuff.c, libgcc2.c. */ +#define OBJECT_FORMAT_ELF + +/* crtstuff.c. transactional memory, + * 0. */ +#define USE_TM_CLONE_REGISTRY 0 + +/* auto-host.h .init_array, .fini_array. */ +#ifdef HAVE_INITFINI_ARRAY_SUPPORT + +/* crtstuff.c. */ +#define USE_INITFINI_ARRAY + +/* .init_array, .fini_array, + * . */ +#undef INIT_SECTION_ASM_OP +#undef FINI_SECTION_ASM_OP + +/* __LIBGCC_INIT_ARRAY_SECTION_ASM_OP__. */ +#define INIT_ARRAY_SECTION_ASM_OP + +/* crtstuff.c */ +#define FINI_ARRAY_SECTION_ASM_OP + +#endif /* HAVE_INITFINI_ARRAY_SUPPORT */ + +#define BITS_PER_UNIT 8 + +/* gthr.h, gthr-posix.h. */ +#define SUPPORTS_WEAK 1 + +/* crtstuff.c. */ +#define TARGET_ATTRIBUTE_WEAK __attribute__ ((weak)) + +/* __LIBGCC_EH_FRAME_SECTION_NAME__. */ +#define EH_FRAME_SECTION_NAME ".eh_frame" + +/* __LIBGCC_EH_TABLES_CAN_BE_READ_ONLY__. */ +#define EH_TABLES_CAN_BE_READ_ONLY 1 + +/* __LIBGCC_DWARF_FRAME_REGISTERS__. */ +#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER + +/* unwind-dw2.c. */ +#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) + +/* __LIBGCC_VTABLE_USES_DESCRIPTORS__. */ +#define TARGET_VTABLE_USES_DESCRIPTORS 0 + +/* libgcov.h, libgcov-driver-system.c. */ +#define TARGET_POSIX_IO + +/* libgcov.h. */ +#define LONG_LONG_TYPE_SIZE 64 + +/* ************************************************************************** */ + +/* , - + * -fbuilding-libgcc. ; + * . */ + +/* crtstuff.c. */ +#define __LIBGCC_EH_TABLES_CAN_BE_READ_ONLY__ EH_TABLES_CAN_BE_READ_ONLY + +/* crtstuff.c. */ +#ifdef EH_FRAME_SECTION_NAME +#define __LIBGCC_EH_FRAME_SECTION_NAME__ EH_FRAME_SECTION_NAME +#endif /* EH_FRAME_SECTION_NAME */ + +/* crtstuff.c. */ +#ifdef CTORS_SECTION_ASM_OP +#define __LIBGCC_CTORS_SECTION_ASM_OP__ CTORS_SECTION_ASM_OP +#endif /* CTORS_SECTION_ASM_OP */ + +/* crtstuff.c. */ +#ifdef DTORS_SECTION_ASM_OP +#define __LIBGCC_DTORS_SECTION_ASM_OP__ DTORS_SECTION_ASM_OP +#endif /* DTORS_SECTION_ASM_OP */ + +/* crtstuff.c. */ +#ifdef TEXT_SECTION_ASM_OP +#define __LIBGCC_TEXT_SECTION_ASM_OP__ TEXT_SECTION_ASM_OP +#endif /* TEXT_SECTION_ASM_OP */ + +/* crtstuff.c, libgcc2.c. */ +#ifdef INIT_SECTION_ASM_OP +#define __LIBGCC_INIT_SECTION_ASM_OP__ INIT_SECTION_ASM_OP +#endif /* INIT_SECTION_ASM_OP */ + +/* crtstuff.c, libgcc2.c. */ +#ifdef INIT_ARRAY_SECTION_ASM_OP +#define __LIBGCC_INIT_ARRAY_SECTION_ASM_OP__ +#endif /* INIT_ARRAY_SECTION_ASM_OP */ + +/* unwind-dw2.c. */ +#if STACK_GROWS_DOWNWARD +#define __LIBGCC_STACK_GROWS_DOWNWARD__ +#endif /* STACK_GROWS_DOWNWARD */ + +/* unwind-dw2.c. */ +#define __LIBGCC_DWARF_FRAME_REGISTERS__ DWARF_FRAME_REGISTERS + +/* unwind-dw2.c */ +#ifdef EH_RETURN_STACKADJ_RTX +#define __LIBGCC_EH_RETURN_STACKADJ_RTX__ +#endif /* EH_RETURN_STACKADJ_RTX */ + +/* libgcov-profiler.c. */ +#define __LIBGCC_VTABLE_USES_DESCRIPTORS__ TARGET_VTABLE_USES_DESCRIPTORS + +#endif /* GCC_TM_H */ diff --git a/libatomic/Makefile.am b/libatomic/Makefile.am index d731406fdbd..d67e6afc388 100644 --- a/libatomic/Makefile.am +++ b/libatomic/Makefile.am @@ -23,7 +23,7 @@ ## . ACLOCAL_AMFLAGS = -I .. -I ../config -SUBDIRS = testsuite +SUBDIRS = ## May be used by toolexeclibdir. gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) diff --git a/libatomic/Makefile.in b/libatomic/Makefile.in index f6eeab312ea..ff50a4df735 100644 --- a/libatomic/Makefile.in +++ b/libatomic/Makefile.in @@ -60,7 +60,7 @@ target_triplet = @target@ @ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@am__append_2 = $(addsuffix _8_1_.lo,$(SIZEOBJS)) @ARCH_X86_64_TRUE@@HAVE_IFUNC_TRUE@am__append_3 = $(addsuffix _16_1_.lo,$(SIZEOBJS)) subdir = . -DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/auto-config.h.in $(srcdir)/../mkinstalldirs \ $(srcdir)/../depcomp @@ -298,7 +298,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I .. -I ../config -SUBDIRS = testsuite +SUBDIRS = gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) \ $(top_srcdir) $(top_builddir) diff --git a/libatomic/configure b/libatomic/configure index c05fc9d1141..eee8e5b7358 100755 --- a/libatomic/configure +++ b/libatomic/configure @@ -8239,7 +8239,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' + lt_prog_compiler_pic='-fPIC' ;; sysv4*MP*) @@ -8366,7 +8366,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' + lt_prog_compiler_pic='-fPIC' ;; osf3* | osf4* | osf5*) @@ -12333,6 +12333,7 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_load/store for size 2" >&5 $as_echo_n "checking for __atomic_load/store for size 2... " >&6; } if test "${libat_cv_have_at_ldst_2+set}" = set; then : @@ -12400,6 +12401,7 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_load/store for size 4" >&5 $as_echo_n "checking for __atomic_load/store for size 4... " >&6; } if test "${libat_cv_have_at_ldst_4+set}" = set; then : @@ -12467,6 +12469,7 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_load/store for size 8" >&5 $as_echo_n "checking for __atomic_load/store for size 8... " >&6; } if test "${libat_cv_have_at_ldst_8+set}" = set; then : @@ -12534,6 +12537,7 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_load/store for size 16" >&5 $as_echo_n "checking for __atomic_load/store for size 16... " >&6; } if test "${libat_cv_have_at_ldst_16+set}" = set; then : @@ -12602,6 +12606,7 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_test_and_set for size 1" >&5 $as_echo_n "checking for __atomic_test_and_set for size 1... " >&6; } if test "${libat_cv_have_at_tas_1+set}" = set; then : @@ -15281,7 +15286,7 @@ else multilib_arg= fi -ac_config_files="$ac_config_files Makefile testsuite/Makefile" +ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -16329,7 +16334,6 @@ do "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "gstdint.h") CONFIG_COMMANDS="$CONFIG_COMMANDS gstdint.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/libatomic/configure.ac b/libatomic/configure.ac index 023f1727b1e..df5bcaf5c8d 100644 --- a/libatomic/configure.ac +++ b/libatomic/configure.ac @@ -263,5 +263,5 @@ else multilib_arg= fi -AC_CONFIG_FILES(Makefile testsuite/Makefile) +AC_CONFIG_FILES(Makefile) AC_OUTPUT diff --git a/libatomic/gcas.c b/libatomic/gcas.c index 63a06c3def9..26bfd691568 100644 --- a/libatomic/gcas.c +++ b/libatomic/gcas.c @@ -73,6 +73,18 @@ } \ } while (0) +#if (defined __LCC__) && (defined __ptr128__) +#undef LARGER +#define LARGER(N) \ + do { \ + /* do nothing (bug #114558) */ \ + if (1) break; \ + /* avoid warnings */ \ + r = 0; a = 0; v = (union max_size_u){ 0 }; \ + if (1) goto Lsucc; else goto Lfail; \ + } while (0) +#endif /* __LCC__ */ + bool @@ -90,7 +102,11 @@ libat_compare_exchange (size_t n, void *mptr, void *eptr, void *dptr, case 2: EXACT(2); goto L4; case 4: EXACT(4); goto L8; case 8: EXACT(8); goto L16; +#if defined(__LCC__) && defined(__ptr128__) && (! HAVE_ATOMIC_CAS_16) + case 16: /* do nothing (mcstbug #125743.4) */ break; +#else case 16: EXACT(16); break; +#endif case 3: L4: LARGER(4); /* FALLTHRU */ case 5 ... 7: L8: LARGER(8); /* FALLTHRU */ diff --git a/libatomic/gexch.c b/libatomic/gexch.c index 44745afa28d..f95eb2fc7be 100644 --- a/libatomic/gexch.c +++ b/libatomic/gexch.c @@ -76,6 +76,17 @@ } \ } while (0) +#if (defined __LCC__) && (defined __ptr128__) +#undef LARGER +#define LARGER(N) \ + do { \ + /* do nothing (bug #114558) */ \ + if (1) break; \ + /* avoid warnings */ \ + r = 0; a = 0; v = (union max_size_u){ 0 }; goto Lfinish; \ + } while (0) +#endif /* __LCC__ */ + static void __attribute__((noinline)) libat_exchange_large_inplace (size_t n, void *mptr, void *vptr) @@ -114,7 +125,11 @@ libat_exchange (size_t n, void *mptr, void *vptr, void *rptr, int smodel) case 2: EXACT(2); goto L4; case 4: EXACT(4); goto L8; case 8: EXACT(8); goto L16; +#if defined(__LCC__) && defined(__ptr128__) && (! HAVE_ATOMIC_EXCHANGE_16) + case 16: /* do nothing (mcstbug #125743.4) */ break; +#else case 16: EXACT(16); break; +#endif case 3: L4: LARGER(4); /* FALLTHRU */ case 5 ... 7: L8: LARGER(8); /* FALLTHRU */ diff --git a/libatomic/gload.c b/libatomic/gload.c index 98e1a7edb9d..083d9fa4a41 100644 --- a/libatomic/gload.c +++ b/libatomic/gload.c @@ -63,6 +63,17 @@ EXACT_ (N, u.C2(i,N), PTR(N,a), goto Lfinish); \ } while (0) +#if (defined __LCC__) && (defined __ptr128__) +#undef LARGER +#define LARGER(N) \ + do { \ + /* do nothing (bug #114558) */ \ + if (1) break; \ + /* avoid warnings */ \ + r = 0; a = 0; goto Lfinish; \ + } while (0) +#endif /* __LCC__ */ + void libat_load (size_t n, void *mptr, void *rptr, int smodel) @@ -77,7 +88,11 @@ libat_load (size_t n, void *mptr, void *rptr, int smodel) case 2: EXACT(2); goto L4; case 4: EXACT(4); goto L8; case 8: EXACT(8); goto L16; +#if defined(__LCC__) && defined(__ptr128__) && (! HAVE_ATOMIC_LDST_16) + case 16: /* do nothing (mcstbug #125743.4) */ break; +#else case 16: EXACT(16); break; +#endif case 3: L4: LARGER(4); /* FALLTHRU */ case 5 ... 7: L8: LARGER(8); /* FALLTHRU */ diff --git a/libatomic/gstore.c b/libatomic/gstore.c index 5c933a379ba..757a8970016 100644 --- a/libatomic/gstore.c +++ b/libatomic/gstore.c @@ -78,6 +78,14 @@ } \ } while (0) +#if (defined __LCC__) && (defined __ptr128__) +#undef LARGER +#define LARGER(N) \ + do { \ + /* do nothing (bug #114558) */ \ + } while (0) +#endif /* __LCC__ */ + void libat_store (size_t n, void *mptr, void *vptr, int smodel) @@ -89,7 +97,11 @@ libat_store (size_t n, void *mptr, void *vptr, int smodel) case 2: EXACT(2); goto L4; case 4: EXACT(4); goto L8; case 8: EXACT(8); goto L16; +#if defined(__LCC__) && defined(__ptr128__) && (! HAVE_ATOMIC_LDST_16) + case 16: /* do nothing (mcstbug #125743.4) */ break; +#else case 16: EXACT(16); break; +#endif case 3: L4: LARGER(4); /* FALLTHRU */ case 5 ... 7: L8: LARGER(8); /* FALLTHRU */ diff --git a/libatomic/libatomic_i.h b/libatomic/libatomic_i.h index 4eb372af280..4457c562db8 100644 --- a/libatomic/libatomic_i.h +++ b/libatomic/libatomic_i.h @@ -213,6 +213,15 @@ DECLARE_ALL_SIZED(4); DECLARE_ALL_SIZED(8); DECLARE_ALL_SIZED(16); +#if defined(__LCC__) && !defined(__OPTIMIZE__) /* См. bug #89377, #87484.5. */ +#if !HAVE_INT16 /* Чтобы не сломать сборку при включении поддержки __int128. */ +#define libat_load_16 ((__typeof__(libat_load_16) *)0) +#define libat_store_16 ((__typeof__(libat_store_16) *)0) +#define libat_exchange_16 ((__typeof__(libat_exchange_16) *)0) +#define libat_compare_exchange_16 ((__typeof__(libat_compare_exchange_16) *)0) +#endif /* !HAVE_INT16 */ +#endif /* defined(__LCC__) && !defined(__OPTIMIZE__) */ + #undef DECLARE_1 #undef DECLARE_ALL_SIZED #undef DECLARE_ALL_SIZED_ diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index a1a392de88d..4be3e1c892a 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -239,8 +239,8 @@ endif # Options to use when compiling libgcc2.a. # -LIBGCC2_DEBUG_CFLAGS = -g -LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ +LIBGCC2_DEBUG_CFLAGS = +LIBGCC2_CFLAGS = $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \ -fbuilding-libgcc -fno-stack-protector \ $(INHIBIT_LIBC_CFLAGS) @@ -290,17 +290,17 @@ INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \ $(INCLUDES) @set_have_cc_tls@ @set_use_emutls@ # Options to use when compiling crtbegin/end. -CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \ +CRTSTUFF_CFLAGS = $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \ $(NO_PIE_CFLAGS) -finhibit-size-directive -fno-inline -fno-exceptions \ - -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \ + -fno-toplevel-reorder \ -fbuilding-libgcc -fno-stack-protector $(FORCE_EXPLICIT_EH_REGISTRY) \ $(INHIBIT_LIBC_CFLAGS) # Extra flags to use when compiling crt{begin,end}.o. CRTSTUFF_T_CFLAGS = -MULTIDIR := $(shell $(CC) $(CFLAGS) -print-multi-directory) -MULTIOSDIR := $(shell $(CC) $(CFLAGS) -print-multi-os-directory) +MULTIDIR := . +MULTIOSDIR := . MULTIOSSUBDIR := $(shell if test $(MULTIOSDIR) != .; then echo /$(MULTIOSDIR); fi) inst_libdir = $(libsubdir)$(MULTISUBDIR) @@ -425,9 +425,9 @@ LIB2ADD += enable-execute-stack.c # While emutls.c has nothing to do with EH, it is in LIB2ADDEH* # instead of LIB2ADD because that's the way to be sure on some targets # (e.g. *-*-darwin*) only one copy of it is linked. -LIB2ADDEH += $(srcdir)/emutls.c -LIB2ADDEHSTATIC += $(srcdir)/emutls.c -LIB2ADDEHSHARED += $(srcdir)/emutls.c +# LIB2ADDEH += $(srcdir)/emutls.c +# LIB2ADDEHSTATIC += $(srcdir)/emutls.c +# LIB2ADDEHSHARED += $(srcdir)/emutls.c # Library members defined in libgcc2.c. lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2 \ diff --git a/libgcc/config.host b/libgcc/config.host index 8beb492b5fa..764527818c8 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -484,6 +484,10 @@ cris-*-elf) cris-*-linux* | crisv32-*-linux*) tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-linux" ;; +e2k-mcst-linux-gnu) + tmake_file="$tmake_file e2k/t-eh-e2k e2k/t-crtalign t-softfp-tf e2k/t-softfp t-softfp e2k/t-linux" + extra_parts="$extra_parts crtalign.o" + ;; epiphany-*-elf* | epiphany-*-rtems*) tmake_file="$tmake_file epiphany/t-epiphany t-fdpbit epiphany/t-custom-eqsf" extra_parts="$extra_parts crti.o crtint.o crtrunc.o crtm1reg-r43.o crtm1reg-r63.o crtn.o" @@ -1195,7 +1199,7 @@ sparc-*-elf*) extra_parts="$extra_parts crti.o crtn.o crtfastmath.o" ;; sparc-*-linux*) # SPARC's running GNU/Linux, libc6 - tmake_file="${tmake_file} t-crtfm" + tmake_file="${tmake_file} t-crtfm sparc/t-crtunaligned" if test "${host_address}" = 64; then tmake_file="$tmake_file sparc/t-linux64" fi @@ -1216,7 +1220,7 @@ sparc-*-linux*) # SPARC's running GNU/Linux, libc6 fi ;; esac - extra_parts="$extra_parts crtfastmath.o" + extra_parts="$extra_parts crtfastmath.o crtunaligned.o" md_unwind_header=sparc/linux-unwind.h ;; sparc-*-rtems*) @@ -1243,8 +1247,8 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*) extra_parts="$extra_parts crtfastmath.o" ;; sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux - extra_parts="$extra_parts crtfastmath.o" - tmake_file="${tmake_file} t-crtfm sparc/t-linux" + extra_parts="$extra_parts crtfastmath.o crtunaligned.o" + tmake_file="${tmake_file} t-crtfm sparc/t-linux sparc/t-crtunaligned" if test "${host_address}" = 64; then tmake_file="${tmake_file} sparc/t-linux64" fi diff --git a/libgcc/config/e2k/crtalign.S b/libgcc/config/e2k/crtalign.S new file mode 100644 index 00000000000..1c1e841899d --- /dev/null +++ b/libgcc/config/e2k/crtalign.S @@ -0,0 +1,15 @@ +#ifndef __e2k__ +#error e2k +#endif + +.section ".init", "ax", @progbits + /* + * + */ + rrs %upsr, %r0 + ors %r0, (1<<2), %r0 + { + rws %r0, %upsr + nop 4 + } + diff --git a/libgcc/config/e2k/libgcc-glibc.ver b/libgcc/config/e2k/libgcc-glibc.ver new file mode 100644 index 00000000000..451964de959 --- /dev/null +++ b/libgcc/config/e2k/libgcc-glibc.ver @@ -0,0 +1,64 @@ +# Copyright (C) 2000-2017 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# In order to work around the very problems that force us to now generally +# create a libgcc.so, glibc reexported a number of routines from libgcc.a. +# By now choosing the same version tags for these specific routines, we +# maintain enough binary compatibility to allow future versions of glibc +# to defer implementation of these routines to libgcc.so via DT_AUXILIARY. + +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + +%inherit GCC_3.0 GLIBC_2.0 +GLIBC_2.0 { + # Sampling of DImode arithmetic used by (at least) i386 and m68k. + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + + # Exception handling support functions used by most everyone. + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + +# mcstbug #120089 +# Used /lib/GNU/gcc-7/libgcc/config/libgcc-glibc.ver +# with additions below +GCC_7.0.0 { + __copysigntf3 + __fabstf2 + __signbittf2 +} diff --git a/libgcc/config/e2k/sfp-exceptions.c b/libgcc/config/e2k/sfp-exceptions.c new file mode 100644 index 00000000000..4dcf4d311ca --- /dev/null +++ b/libgcc/config/e2k/sfp-exceptions.c @@ -0,0 +1,32 @@ +#include "sfp-machine.h" + +void __attribute__ ((optimize(0))) +__sfp_handle_exceptions (int _fex) +{ + const double max = __DBL_MAX__; + const double min = __DBL_MIN__; + const double zero = 0.0; + const double one = 1.0; + volatile double r; + + if (_fex & FP_EX_INVALID) + { + r = zero / zero; + } + if (_fex & FP_EX_DIVZERO) + { + r = one / zero; + } + if (_fex & FP_EX_OVERFLOW) + { + r = max + max; + } + if (_fex & FP_EX_UNDERFLOW) + { + r = min * min; + } + if (_fex & FP_EX_INEXACT) + { + r = max - one; + } +} diff --git a/libgcc/config/e2k/sfp-machine.h b/libgcc/config/e2k/sfp-machine.h new file mode 100644 index 00000000000..85270204fcc --- /dev/null +++ b/libgcc/config/e2k/sfp-machine.h @@ -0,0 +1,100 @@ +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long long +#define _FP_WS_TYPE signed long long +#define _FP_I_TYPE long long + +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); + +#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) + +/* The type of the result of a floating point comparison. This must + match `__libgcc_cmp_return__' in GCC for the target. */ +typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#define CMPtype __gcc_CMPtype + +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S _FP_QNANBIT_S +#define _FP_NANFRAC_D _FP_QNANBIT_D +#define _FP_NANFRAC_E _FP_QNANBIT_E, 0 +#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 + +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + +#define _FP_NANSIGN_S 1 +#define _FP_NANSIGN_D 1 +#define _FP_NANSIGN_E 1 +#define _FP_NANSIGN_Q 1 + +/* Here is something Intel misdesigned: the specs don't define + the case where we have two NaNs with same mantissas, but + different sign. Different operations pick up different NaNs. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if (_FP_FRAC_GT_##wc(X, Y) \ + || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + else \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define _FP_TININESS_AFTER_ROUNDING 1 + +#define FP_EX_INVALID 0x01 +#define FP_EX_DENORM 0x02 +#define FP_EX_DIVZERO 0x04 +#define FP_EX_OVERFLOW 0x08 +#define FP_EX_UNDERFLOW 0x10 +#define FP_EX_INEXACT 0x20 +#define FP_EX_ALL \ + (FP_EX_INVALID | FP_EX_DENORM | FP_EX_DIVZERO | FP_EX_OVERFLOW \ + | FP_EX_UNDERFLOW | FP_EX_INEXACT) + +void __sfp_handle_exceptions (int); + +#define FP_HANDLE_EXCEPTIONS \ + do { \ + if (__builtin_expect (_fex, 0)) \ + __sfp_handle_exceptions (_fex); \ + } while (0) + +#define FP_TRAPPING_EXCEPTIONS ((~_pfpfr >> 7) & FP_EX_ALL) + +#define FP_RND_NEAREST 0x0000 +#define FP_RND_ZERO 0x6000 +#define FP_RND_PINF 0x4000 +#define FP_RND_MINF 0x2000 +#define FP_RND_MASK 0x6000 + +#define _FP_DECL_EX \ + unsigned int _pfpfr __attribute__ ((unused)) = FP_RND_NEAREST + +#define FP_INIT_ROUNDMODE \ + _Pragma ("asm_inline") __asm__ __volatile ("rrs %%pfpfr, %0" : "=r" (_pfpfr)) + +#define FP_ROUNDMODE (_pfpfr & FP_RND_MASK) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __LITTLE_ENDIAN + +/* Define ALIASNAME as a strong alias for NAME. */ +#define strong_alias(name, aliasname) _strong_alias(name, aliasname) +#define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +#pragma diag_suppress 62 /* "shift count is negative" */ +#pragma diag_suppress 63 /* "shift count is too large" */ diff --git a/libgcc/config/e2k/t-crtalign b/libgcc/config/e2k/t-crtalign new file mode 100644 index 00000000000..b450b93a132 --- /dev/null +++ b/libgcc/config/e2k/t-crtalign @@ -0,0 +1,2 @@ +crtalign.o: $(srcdir)/config/e2k/crtalign.S + $(gcc_compile) -c -x assembler-with-cpp $< diff --git a/libgcc/config/e2k/t-eh-e2k b/libgcc/config/e2k/t-eh-e2k new file mode 100644 index 00000000000..dc773fd5c65 --- /dev/null +++ b/libgcc/config/e2k/t-eh-e2k @@ -0,0 +1,6 @@ +LIB2ADDEH = $(srcdir)/config/e2k/unwind-dw2-e2k.c $(srcdir)/unwind-dw2-fde-dip.c \ + $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c + +# liblcc.a should be linked into libgcc_s.so for the sake of runtime support of +# `__builtin_cpu_is ()' in the latter. +SHLIB_LC = -llcc -lc diff --git a/libgcc/config/e2k/t-linux b/libgcc/config/e2k/t-linux new file mode 100644 index 00000000000..53ca277b7bd --- /dev/null +++ b/libgcc/config/e2k/t-linux @@ -0,0 +1,3 @@ +# Override t-slibgcc-elf-ver to export some libgcc symbols with +# the symbol versions that glibc used. +SHLIB_MAPFILES += $(srcdir)/config/e2k/libgcc-glibc.ver diff --git a/libgcc/config/e2k/t-softfp b/libgcc/config/e2k/t-softfp new file mode 100644 index 00000000000..5f4a953bd25 --- /dev/null +++ b/libgcc/config/e2k/t-softfp @@ -0,0 +1,5 @@ +# Provide fallbacks for __builtin_copysignq, __builtin_fabsq +# and __builtin_signbitq. +LIB2ADD += $(srcdir)/config/e2k/tf-signs.c + +LIB2ADD += $(srcdir)/config/e2k/sfp-exceptions.c diff --git a/libgcc/config/e2k/tf-signs.c b/libgcc/config/e2k/tf-signs.c new file mode 100644 index 00000000000..68d42d38fb9 --- /dev/null +++ b/libgcc/config/e2k/tf-signs.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2008-2017 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +union _FP_UNION_Q +{ + __float128 flt; + struct + { + unsigned long long frac0 : 64; + unsigned long long frac1 : 48; + unsigned exp : 15; + unsigned sign : 1; + } bits __attribute__((packed)); +}; + +__float128 __copysigntf3 (__float128, __float128); +__float128 __fabstf2 (__float128); +int __signbittf2 (__float128); + +__float128 +__copysigntf3 (__float128 a, __float128 b) +{ + union _FP_UNION_Q A, B; + + A.flt = a; + B.flt = b; + A.bits.sign = B.bits.sign; + + return A.flt; +} + +__float128 +__fabstf2 (__float128 a) +{ + union _FP_UNION_Q A; + + A.flt = a; + A.bits.sign = 0; + + return A.flt; +} + +int +__signbittf2 (__float128 a) +{ + union _FP_UNION_Q A; + + A.flt = a; + + return A.bits.sign; +} diff --git a/libgcc/config/e2k/unwind-dw2-e2k.c b/libgcc/config/e2k/unwind-dw2-e2k.c new file mode 100644 index 00000000000..a4c522460e2 --- /dev/null +++ b/libgcc/config/e2k/unwind-dw2-e2k.c @@ -0,0 +1,1127 @@ +/* DWARF2 exception handling and frame unwind runtime interface routines. + Copyright (C) 1997-2015 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#include "unwind.h" +#include "unwind-pe.h" +#include "unwind-dw2-fde.h" +#include "unwind-dw2.h" + +#ifdef HAVE_SYS_SDT_H +#include +#endif + +#if defined __linux__ +# include +/* For SYS_{access_hw_stacks,set_backtrace} which . . . */ +# include +#elif defined __QNX__ +# include +/* . . . are not provided by QNX libc headers. */ +# define SYS_access_hw_stacks __NR_access_hw_stacks +# define SYS_set_backtrace __NR_set_backtrace +#else +#error "Unsupported OS" +#endif + +#if ! defined (__ptr128__) +# define syshw(m, f, b, s, r) \ + syscall (SYS_access_hw_stacks, (unsigned long) m, f, b, s, r) +#else /* defined (__ptr128__) */ +# if ! defined (__NEW_PM_SYSCALLS) +# define syshw(m, f, b, s, r) \ + syscall (SYS_access_hw_stacks, (((unsigned long) m) << 32) | s, f, b, r) +#else /* defined (__NEW_PM_SYSCALLS) */ +# define syshw(m, f, b, s, r) \ + syscall (SYS_access_hw_stacks, (void *) m, (void *) f, \ + (void *) b, (void *) s, (void *) r) +#endif /* defined __NEW_PM_SYSCALLS */ +#endif /* defined (__ptr128__) */ + +#if ! defined (__ptr128__) || ! defined (__NEW_PM_SYSCALLS) +# define sys_set_backtrace(a, b, c, d) syscall (SYS_set_backtrace, a, b, c, d) +#else /* defined (__ptr128__) && defined (__NEW_PM_SYSCALLS) */ +# define sys_set_backtrace(a, b, c, d) syscall (SYS_set_backtrace, \ + (void *) a, (void *) b, \ + (void *) c, (void *) d) +#endif /* defined (__ptr128__) && defined (__NEW_PM_SYSCALLS) */ + +#ifndef __USING_SJLJ_EXCEPTIONS__ + +/* Definitions of E2K-specific register types and macros. */ + +#define E2K_VA_SIZE 48 +#define E2K_VA_MSB (E2K_VA_SIZE - 1) + +typedef struct e2k_rusd_lo_fields { /* Fields of lower word */ + unsigned long long base : E2K_VA_SIZE; /* [47: 0] */ + unsigned long long unused2 : 57 - E2K_VA_MSB; /* [57:48] */ + unsigned long long p : 1; /* [58] */ + unsigned long long rw : 2; /* [60:59] */ + unsigned long long unused : 3; /* [63:61] */ +} e2k_rusd_lo_fields_t; + +/* Structure of lower word */ +typedef union e2k_rusd_lo_struct { + e2k_rusd_lo_fields_t fields; /* as USD fields */ + unsigned long long word; /* as entire register */ +} e2k_rusd_lo_struct_t; + + + +typedef struct e2k_rwap_lo_fields { /* Fields of lower word */ + unsigned long long base : E2K_VA_SIZE; /* [47: 0] */ + unsigned long long unused2 : 55 - E2K_VA_MSB; /* [55:48] */ + unsigned long long stub3 : 1; /* [56] */ + unsigned long long stub2 : 1; /* [57] */ + unsigned long long stub1 : 1; /* [58] */ + unsigned long long rw : 2; /* [60:59] */ + unsigned long long itag : 3; /* [63:61] */ +} e2k_rwap_lo_fields_t; + + +/* Structure of lower word */ +typedef union e2k_rwap_lo_struct { + e2k_rwap_lo_fields_t fields; /* as AP fields */ + unsigned long long word; /* as entire register */ +} e2k_rwap_lo_struct_t; + +/* Fields of high word */ +typedef struct e2k_rwap_hi_fields { +unsigned long long curptr : 32; /* [31: 0] */ +unsigned long long size : 32; /* [63:32] */ +} e2k_rwap_hi_fields_t; + +/* Structure of high word */ +typedef union e2k_rwap_hi_struct { + e2k_rwap_hi_fields_t fields; /* as AP fields */ + unsigned long long word; /* as entire register */ +} e2k_rwap_hi_struct_t; + +typedef e2k_rwap_lo_struct_t e2k_pcsp_lo_t; +typedef e2k_rwap_lo_struct_t e2k_psp_lo_t; +typedef e2k_rwap_hi_struct_t e2k_pcsp_hi_t; +typedef e2k_rwap_hi_struct_t e2k_psp_hi_t; +typedef e2k_rusd_lo_struct_t e2k_rusd_lo_t; +typedef e2k_rwap_hi_struct_t e2k_rusd_hi_t; + + +/* Structure of cr0_hi chain reg */ +typedef struct e2k_cr0_hi_fields { + unsigned long long unused_1 : 3; /* [ 2: 0] */ + unsigned long long ip : 45; /* [47: 3] */ + unsigned long long unused_2 : 16; /* [48:63] */ +} e2k_cr0_hi_fields_t; + +typedef union e2k_cr0_hi { + e2k_cr0_hi_fields_t fields; /* as fields */ + unsigned long long word; /* as entire register */ +} e2k_cr0_hi_t; + + +/* Structure of cr1_lo chain reg */ +typedef union e2k_cr1_lo_fields { + struct { + unsigned long long tr : 15; /* [14: 0] */ + unsigned long long unused1 : 1; /* [15] */ + unsigned long long ein : 8; /* [23:16] */ + unsigned long long unused2 : 1; /* [24] */ + unsigned long long wfx : 1; /* [25] */ + unsigned long long wpsz : 7; /* [32:26] */ + unsigned long long wbs : 7; /* [39:33] */ + unsigned long long cuir : 17; /* [56:40] */ + unsigned long long psr : 7; /* [63:57] */ + }; + struct { + unsigned long long __x1 : 57; /* [56:0] */ + unsigned long long pm : 1; /* [57] */ + unsigned long long ie : 1; /* [58] */ + unsigned long long sge : 1; /* [59] */ + unsigned long long lw : 1; /* [60] last wish */ + unsigned long long uie : 1; /* [61] user interrupts enable */ + unsigned long long nmie : 1; /* [62] not masked interrupts enable */ + unsigned long long unmie : 1; /* [63] user not masked interrupts */ + /* enable */ + }; +} e2k_cr1_lo_fields_t; + +typedef union e2k_cr1_lo { + e2k_cr1_lo_fields_t fields; /* as fields */ + unsigned long long word; /* as entire register */ +} e2k_cr1_lo_t; + +typedef union e2k_cr1_hi_fields { /* Structure of cr1_hi chain reg */ + struct { + unsigned long long br : 28; /* [27: 0] */ + unsigned long long unused : 7; /* [34:28] */ + unsigned long long wdbl : 1; /* [35:35] */ + unsigned long long ussz : 28; /* [63:36] */ + }; +} e2k_cr1_hi_fields_t; +typedef union e2k_cr1_hi { + e2k_cr1_hi_fields_t fields; /* as fields */ + unsigned long long word; /* as entire register */ +} e2k_cr1_hi_t; + + +typedef struct e2k_mem_crstack { + unsigned long long cr0_lo; + e2k_cr0_hi_t cr0_hi; + e2k_cr1_lo_t cr1_lo; + e2k_cr1_hi_t cr1_hi; +} e2k_mem_crs_t; + + +#define AW(x) (x.word) +#define AS(x) (x.fields) + +#define E2K_PSHTP_SIZE 12 +#define PSHTP_SIGN_EXTEND(pshtp) \ + ((unsigned long long) (((long long) (pshtp) << (64 - E2K_PSHTP_SIZE)) \ + >> (64 - E2K_PSHTP_SIZE))) + +#define E2K_PCSHTP_SIZE 11 +#define PCSHTP_SIGN_EXTEND(pcshtp) \ + ((unsigned long long) (((long long) (pcshtp) << (64 - E2K_PCSHTP_SIZE)) \ + >> (64 - E2K_PCSHTP_SIZE))) + + +#define E2K_READ_STACK_REGS(pcsp_lo, pcsp_hi, psp_lo, psp_hi, pcshtp, pshtp) \ +do { \ + char tmp = 0, val; \ + asm volatile ("1:\n" \ + "ldb,0 0, %[tmp], %[val], mas=0x7\n" \ + "rrd %%pcshtp, %[__pcshtp]\n" \ + "rrd %%pcsp.lo, %[__pcsp_lo]\n" \ + "rrd %%pcsp.hi, %[__pcsp_hi]\n" \ + "rrd %%pshtp, %[__pshtp]\n" \ + "rrd %%psp.lo, %[__psp_lo]\n" \ + "rrd %%psp.hi, %[__psp_hi]\n" \ + "{\n" \ + " stb,2 0, %[tmp], %[val], mas = 0x2\n" \ + " ibranch 1b ? %%MLOCK\n" \ + "}\n" \ + : [val] "=&r" (val), \ + [__pcsp_lo] "=&r" (pcsp_lo), \ + [__pcsp_hi] "=&r" (pcsp_hi), \ + [__psp_lo] "=&r" (psp_lo), \ + [__psp_hi] "=&r" (psp_hi), \ + [__pcshtp] "=&r" (pcshtp), \ + [__pshtp] "=&r" (pshtp) \ + : [tmp] "r" (&tmp)); \ + } while (0) + + +#define EXT_QREG_SZ 32 + +#if ! defined (__ptr128__) +typedef void * typeof_ra; +#else /* defined (__ptr128__) */ +typedef _Unwind_Ptr typeof_ra; +#endif /* defined (__ptr128__) */ + +/* The length of chain stack cache allowing us not to make access_hw_stacks + syscall for each unwound frame. */ +#define CHAIN_STACK_CACHE_LEN 32 + +/* This is the register and unwind state for a particular frame. This + provides the information necessary to unwind up past a frame and return + to its caller. */ +struct _Unwind_Context +{ + size_t psp_offset; + e2k_mem_crs_t *chain_stack; + size_t chain_stack_size; + size_t pcsp_idx; + unsigned long long us_base; + typeof_ra ra; + unsigned long long prev_ps_frame_size; + unsigned long long prev_us_size; + void *lsda; + struct dwarf_eh_bases bases; + size_t level; + + /* Which parameters have been set by _Unwind_SetGR () and . . . */ + int set[2]; + /* . . . their values in case they have. */ +#if ! defined __ptr128__ + unsigned long long param0; +#else /* defined __ptr128__ */ + void *param0; +#endif /* defined __ptr128__ */ + unsigned long long param1; +}; + + +/* Read unaligned data from the instruction buffer. */ + +union unaligned +{ + void *p; + unsigned u2 __attribute__ ((mode (HI))); + unsigned u4 __attribute__ ((mode (SI))); + unsigned u8 __attribute__ ((mode (DI))); + signed s2 __attribute__ ((mode (HI))); + signed s4 __attribute__ ((mode (SI))); + signed s8 __attribute__ ((mode (DI))); +} __attribute__ ((packed)); + +static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *); +static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *, + _Unwind_FrameState *); + +static inline void * +read_pointer (const void *p) { const union unaligned *up = p; return up->p; } + +static inline int +read_1u (const void *p) { return *(const unsigned char *) p; } + +static inline int +read_1s (const void *p) { return *(const signed char *) p; } + +static inline int +read_2u (const void *p) { const union unaligned *up = p; return up->u2; } + +static inline int +read_2s (const void *p) { const union unaligned *up = p; return up->s2; } + +static inline unsigned int +read_4u (const void *p) { const union unaligned *up = p; return up->u4; } + +static inline int +read_4s (const void *p) { const union unaligned *up = p; return up->s4; } + +static inline unsigned long +read_8u (const void *p) { const union unaligned *up = p; return up->u8; } + +static inline unsigned long +read_8s (const void *p) { const union unaligned *up = p; return up->s8; } + +static inline _Unwind_Word +_Unwind_IsSignalFrame (struct _Unwind_Context *context + __attribute__ ((unused))) +{ + return 0; +} + +static inline void +_Unwind_SetSignalFrame (struct _Unwind_Context *context + __attribute__ ((unused)), + int val __attribute__ ((unused))) +{ +} + + +/* Get the value of register INDEX as saved in CONTEXT. */ + +inline _Unwind_Word +_Unwind_GetGR (struct _Unwind_Context *context __attribute__ ((unused)), + int index __attribute__ ((unused))) +{ + return 0; +} + +static inline void * +_Unwind_GetPtr (struct _Unwind_Context *context, int index) +{ + return (void *)(_Unwind_Ptr) _Unwind_GetGR (context, index); +} + +/* Get the value of the CFA as saved in CONTEXT. */ +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + return (_Unwind_Word) (context->us_base + context->prev_us_size); +} + + +/* Get the value of the previous %pcsp as saved in CONTEXT. */ +_Unwind_Word +_Unwind_GetPCSP (struct _Unwind_Context *context) +{ + return (_Unwind_Word) ((context->pcsp_idx - 1) << 5); +} + + +/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ + +inline void +_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) +{ + /* LCC rather naively believes that `%b[0], . . ., %b[63]' registers have + their "gnu numbers" (have you ever heard of such a concept?) in the range + from 64 to 127 inclusively (see `mdes_e2k_RegTable[]' in `mdes/mdes_e2k_ + reg.c'; interestingly enough `%b[64], . . ., %b[127]' have `-1' specified + for their "gnu numbers"). Support this point of view here. + + FIXME: e2k-linux-gcc is currently aware only of `%r0, . . ., %r15' and + `%b[0], . . ., %b[7]' and enumerates them from 0 to 15 and from 17 to 24 + inclusively. This is almost sure to make libgcc compiled by `{e2k-linux-gcc + ,lcc}' and other libraries like libstdc++ making use of `_Unwind_SetGR + (__builtin_eh_return_data_regno ())' compiled by `{lcc,e2k-linux-gcc}' + incompatible with each other at runtime. */ + +#if defined __LCC__ +# define FIRST_DIRECT_REG 0 +# define LAST_DIRECT_REG 63 +# define FIRST_BASED_REG 64 +# define LAST_BASED_REG 127 +#else /* ! defined __LCC__ */ +# define FIRST_DIRECT_REG 0 +# define LAST_DIRECT_REG 15 +# define FIRST_BASED_REG 17 +# define LAST_BASED_REG 24 +#endif /* ! defined __LCC__ */ + +#if ! defined __ptr128__ + if (index == FIRST_BASED_REG) + { + context->param0 = (unsigned long long) val; + context->set[0] = 1; + } + else +#endif /* ! defined __ptr128__ */ + if ( +#if ! defined __ptr128__ + index == FIRST_BASED_REG + 1 +#else /* defined __ptr128__ */ + index == FIRST_BASED_REG + 2 +#endif /* defined __ptr128__ */ + ) + { + context->param1 = (unsigned long long) val; + context->set[1] = 1; + } + else + abort (); +} + +/* Get the pointer to a register INDEX as saved in CONTEXT. */ + +static inline void * +_Unwind_GetGRPtr (struct _Unwind_Context *context __attribute__ ((unused)), + int index __attribute__ ((unused))) +{ + return (void *) 0; +} + +/* Set the pointer to a register INDEX as saved in CONTEXT. */ +#if defined (__ptr128__) +void +_Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) +{ + if (index == FIRST_BASED_REG) + { + context->param0 = p; + context->set[0] = 1; + } + else + /* Should not be used otherwise. */ + abort (); +} +#endif /* defined (__ptr128__) */ + +/* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ + +static inline void +_Unwind_SetGRValue (struct _Unwind_Context *context __attribute__ ((unused)), + int index __attribute__ ((unused)), + _Unwind_Word val __attribute__ ((unused))) +{ +} + +/* Return nonzero if register INDEX is stored by value rather than + by reference. */ + +static inline int +_Unwind_GRByValue (struct _Unwind_Context *context __attribute__ ((unused)), + int index __attribute__ ((unused))) +{ + return 0; +} + +/* Retrieve the return address for CONTEXT. */ + +inline _Unwind_Ptr +_Unwind_GetIP (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->ra; +} + +/* Retrieve the return address and flag whether that IP is before + or after first not yet fully executed instruction. */ + +inline _Unwind_Ptr +_Unwind_GetIPInfo (struct _Unwind_Context *context, + int *ip_before_insn __attribute__ ((unused))) +{ + *ip_before_insn = _Unwind_IsSignalFrame (context); + return (_Unwind_Ptr) context->ra; +} + +/* Overwrite the return address for CONTEXT with VAL. */ + +inline void +_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) +{ + context->ra = (typeof_ra) val; +} + +void * +_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) +{ + return context->lsda; +} + +_Unwind_Ptr +_Unwind_GetRegionStart (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.func; +} + +void * +_Unwind_FindEnclosingFunction ( +#ifndef __ptr128__ + void *pc +#else + _Unwind_Ptr pc +#endif + ) +{ + struct dwarf_eh_bases bases; + const struct dwarf_fde *fde = _Unwind_Find_FDE (pc - 1, &bases); + if (fde) + return bases.func; + else + return NULL; +} + +_Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.dbase; +} + +_Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *context) +{ + return (_Unwind_Ptr) context->bases.tbase; +} + +#include "md-unwind-support.h" + +/* Extract any interesting information from the CIE for the translation + unit F belongs to. Return a pointer to the byte after the augmentation, + or NULL if we encountered an undecipherable augmentation. */ + +static const unsigned char * +extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + const unsigned char *aug = cie->augmentation; + const unsigned char *p = aug + strlen ((const char *)aug) + 1; + const unsigned char *ret = NULL; + _uleb128_t utmp; + _sleb128_t stmp; + + /* g++ v2 "eh" has pointer immediately following augmentation string, + so it must be handled first. */ + if (aug[0] == 'e' && aug[1] == 'h') + { + fs->eh_ptr = read_pointer (p); + p += sizeof (void *); + aug += 2; + } + + /* After the augmentation resp. pointer for "eh" augmentation + follows for CIE version >= 4 address size byte and + segment size byte. */ + if (__builtin_expect (cie->version >= 4, 0)) + { + if (p[0] != sizeof (void *) || p[1] != 0) + return NULL; + p += 2; + } + /* Immediately following this are the code and + data alignment and return address column. */ + p = read_uleb128 (p, &utmp); + fs->code_align = (_Unwind_Word)utmp; + p = read_sleb128 (p, &stmp); + fs->data_align = (_Unwind_Sword)stmp; + if (cie->version == 1) + fs->retaddr_column = *p++; + else + { + p = read_uleb128 (p, &utmp); + fs->retaddr_column = (_Unwind_Word)utmp; + } + fs->lsda_encoding = DW_EH_PE_omit; + + /* If the augmentation starts with 'z', then a uleb128 immediately + follows containing the length of the augmentation field following + the size. */ + if (*aug == 'z') + { + p = read_uleb128 (p, &utmp); + ret = p + utmp; + + fs->saw_z = 1; + ++aug; + } + + /* Iterate over recognized augmentation subsequences. */ + while (*aug != '\0') + { + /* "L" indicates a byte showing how the LSDA pointer is encoded. */ + if (aug[0] == 'L') + { + fs->lsda_encoding = *p++; + aug += 1; + } + + /* "R" indicates a byte indicating how FDE addresses are encoded. */ + else if (aug[0] == 'R') + { + fs->fde_encoding = *p++; + aug += 1; + } + + /* "P" indicates a personality routine in the CIE augmentation. */ + else if (aug[0] == 'P') + { +#ifndef __ptr128__ + _Unwind_Ptr personality; + p = read_encoded_value (context, *p, p + 1, &personality); + fs->personality = (_Unwind_Personality_Fn) personality; +#else + p = read_encoded_ptr (context, *p, p + 1, + (void **) (void *) &fs->personality); +#endif + + aug += 1; + } + + /* "S" indicates a signal frame. */ + else if (aug[0] == 'S') + { + fs->signal_frame = 1; + aug += 1; + } + + /* Otherwise we have an unknown augmentation string. + Bail unless we saw a 'z' prefix. */ + else + return ret; + } + + return ret ? ret : p; +} + + + +/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for + its caller and decode it into FS. This function also sets the + args_size and lsda members of CONTEXT, as they are really information + about the caller's frame. */ + +static _Unwind_Reason_Code +uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + const struct dwarf_fde *fde; + const struct dwarf_cie *cie; + const unsigned char *aug, *insn; + + memset (fs, 0, sizeof (*fs)); + context->lsda = 0; + + /* At `pcsp_idx == 1' we are almost certainly left with one or two pure C + frames containing no unwind data. However, find out why it turns out to + be impossible to reach `pcsp_idx == 0' here. */ + if (context->pcsp_idx == 1 + || context->ra == 0) + return _URC_END_OF_STACK; + + fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1, + &context->bases); + + /* Make E2K unwinder silently skip C frames compiled without `-fexceptions' + instead of stopping at the first of them which was the reason for + Bug #90378. This is a significant benefit of E2K architecture which is + going to save us the trouble of recompiling tons of C sources intended for + use in (together with) C++ exception throwing applications. */ + if (fde == NULL) + return _URC_NO_REASON; + + + cie = get_cie (fde); + insn = extract_cie_info (cie, context, fs); + if (insn == NULL) + /* CIE contained unknown augmentation. */ + return _URC_FATAL_PHASE1_ERROR; + + + /* Locate augmentation for the fde. */ + aug = (const unsigned char *) fde + sizeof (*fde); + aug += 2 * size_of_encoded_value (fs->fde_encoding); + insn = NULL; + if (fs->saw_z) + { + _uleb128_t i; + aug = read_uleb128 (aug, &i); + insn = aug + i; + } + if (fs->lsda_encoding != DW_EH_PE_omit) + { +#if ! defined (__ptr128__) + _Unwind_Ptr lsda; + aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda); + context->lsda = (void *) lsda; +#else /* defined (__ptr128__) */ + aug = read_encoded_ptr (context, fs->lsda_encoding, aug, &context->lsda); +#endif /* defined (__ptr128__) */ + } + + return _URC_NO_REASON; +} + +typedef union { _Unwind_Ptr ptr; _Unwind_Word word; } _Unwind_SpTmp; + +static void +fill_in_chain_stack_fragm (struct _Unwind_Context *context) +{ + unsigned long long frames_num + = (context->pcsp_idx < CHAIN_STACK_CACHE_LEN + ? context->pcsp_idx + : CHAIN_STACK_CACHE_LEN); + size_t size = 32 * frames_num; + unsigned long long top = 32 * (context->pcsp_idx - frames_num); + + if (syshw (E2K_READ_CHAIN_STACK_EX, &top, + &context->chain_stack[CHAIN_STACK_CACHE_LEN - frames_num], size, + NULL) != 0) + abort (); +} + + + +/* CONTEXT describes the unwind state for a frame, and FS describes the FDE + of its caller. Update CONTEXT to refer to the caller as well. Note + that the args_size and lsda members are not updated here, but later in + uw_frame_state_for. */ + +static void +uw_update_context (struct _Unwind_Context *context, + _Unwind_FrameState *fs __attribute__ ((unused))) +{ + do { + e2k_mem_crs_t crs; + + context->psp_offset -= context->prev_ps_frame_size; + + if ((context->chain_stack_size - context->pcsp_idx) % CHAIN_STACK_CACHE_LEN + == 0) + fill_in_chain_stack_fragm (context); + + crs = context->chain_stack[CHAIN_STACK_CACHE_LEN - 1 + - ((context->chain_stack_size + - context->pcsp_idx) + % CHAIN_STACK_CACHE_LEN)]; + context->pcsp_idx--; + + context->prev_ps_frame_size = AS (crs.cr1_lo).wbs * EXT_QREG_SZ; + context->prev_us_size = AS (crs.cr1_hi).ussz << 4; + context->ra = (typeof_ra) (unsigned long) (AS (crs.cr0_hi).ip << 3); + } + while (context->ra == 0); + + ++context->level; +} + +static void +uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + uw_update_context (context, fs); +} + +/* This macro is separately called from `_Unwind_RaiseException ()' via `reinit + _chain_stack_cache ()' to make chain stack cache in THIS_CONTEXT match its + state prior to starting phase 2 as it may have been changed at phase 1 on + behalf of CUR_CONTEXT now that it's shared between `{THIS,CUR}_CONTEXT'. + FIXME: consider unifying it with `fill_in_chain_stack_fragm ()'. */ +#define init_chain_stack_cache(context) \ + { \ + size_t fragm_idx; \ + size_t fragm_size; \ + size_t obtained_size; \ + unsigned long long top; \ + \ + if (context->pcsp_idx < CHAIN_STACK_CACHE_LEN) \ + { \ + fragm_idx = CHAIN_STACK_CACHE_LEN - context->pcsp_idx; \ + fragm_size = context->pcsp_idx; \ + } \ + else \ + { \ + fragm_idx = 0; \ + fragm_size = CHAIN_STACK_CACHE_LEN; \ + } \ + \ + obtained_size = 32 * fragm_size; \ + \ + top = 32 * (context->chain_stack_size - fragm_size); \ + \ + if (syshw (E2K_READ_CHAIN_STACK_EX, &top, \ + &context->chain_stack[fragm_idx], \ + obtained_size, NULL) \ + != 0) \ + abort (); \ + \ + } \ + +static void __attribute__ ((noinline)) +reinit_chain_stack_cache (struct _Unwind_Context *context) +{ + init_chain_stack_cache (context); +} + +/* Fill in CONTEXT for top-of-stack. The only valid registers at this + level will be the return address and the CFA. */ +static void __attribute__((noinline)) +uw_init_context (struct _Unwind_Context *context, + e2k_mem_crs_t *chain_stack) +{ + int i; + e2k_rusd_lo_t usd_lo; + e2k_rusd_hi_t usd_hi; + typeof_ra ra; + _Unwind_FrameState fs; + _Unwind_Reason_Code code; +#if defined (__ptr128__) && defined SHARED + static int syscall_lazily_resolved; +#endif /* defined (__ptr128__) && defined SHARED */ + + ra = (typeof_ra) __builtin_extract_return_addr (__builtin_return_address (0)); + + memset (context, 0, sizeof (struct _Unwind_Context)); + + /* I can't rely on the equivalent "standard" macro provided by + since it has been renamed in linux-4.x (Bug #101373). */ +#define GET_STATE_REG(reg_mnemonic) \ + ({ \ + register unsigned long long res; \ + asm volatile ("rrd \t%%" #reg_mnemonic ", %0" \ + : "=r" (res)); \ + res; \ + }) + + AW (usd_lo) = GET_STATE_REG (usd.lo); + AW (usd_hi) = GET_STATE_REG (usd.hi); +#undef GET_STATE_REG + + context->us_base = AS (usd_lo).base - AS (usd_hi).size; + +#if defined (__ptr128__) && defined SHARED + /* Ensure that `syscall ()' has already been resolved lazily by the time of + `syshw (E2K_GET_PROCEDURE_STACK_SIZE)' invocation below. Otherwise, one may + get inconsistent sizes for procedure and chain stacks due to an extra call + frame imposed by lazy binding in PM. */ + if (! syscall_lazily_resolved) + { + /* Use any unimplemented syscall number here to avoid any side effects. + However, avoid using `__NR_restart_syscall == 0' as this results in + a rather weird halt or an infinite loop (?) if the thread is cancelled + while being within a (restartable?) system call. */ + syscall (424); + + /* FIXME: shouldn't this be done in MT-safe way? The failure to do so may + probably result in redundant invocations of `syscall (0)' in the worst + case. */ + syscall_lazily_resolved = 1; + } +#endif /* defined (__ptr128__) && defined SHARED */ + + /* Determine the sizes of hardware stacks. */ + if (syshw (E2K_GET_PROCEDURE_STACK_SIZE, NULL, NULL, 0, + &context->psp_offset) != 0) + abort ();/***/ + + if (syshw (E2K_GET_CHAIN_STACK_SIZE, NULL, NULL, 0, + &context->chain_stack_size) != 0) + abort (); + + + if ((context->chain_stack_size & 0x1f) != 0) + abort (); + + context->chain_stack_size >>= 5; + context->pcsp_idx = context->chain_stack_size; + +#if defined __ptr128__ + /* FIXME: chain stack cache needs to be zero out because of a rather + suspicious LSIM behaviour in PM: something irrelevant is found in + it after E2K_READ_CHAIN_STACK_EX if it hasn't been preinitialized. */ + memset (chain_stack, 0, CHAIN_STACK_CACHE_LEN * sizeof (e2k_mem_crs_t)); +#endif /* defined __ptr128__ */ + context->chain_stack = chain_stack; + init_chain_stack_cache (context); + + for (i = CHAIN_STACK_CACHE_LEN - 1; i >= 0 && context->pcsp_idx != 0; i--) + { + e2k_mem_crs_t crs; + + crs = context->chain_stack[i]; + + context->ra = (typeof_ra) (unsigned long) (AS (crs.cr0_hi).ip << 3); + context->prev_ps_frame_size = AS (crs.cr1_lo).wbs * EXT_QREG_SZ; + context->prev_us_size = AS (crs.cr1_hi).ussz << 4; + + context->pcsp_idx--; + + if (context->ra != ra) + context->psp_offset -= context->prev_ps_frame_size; + else + break; + } + + if (i < 0 || context->pcsp_idx == 0) + abort (); + + context->level = 0; + + code = uw_frame_state_for (context, &fs); + gcc_assert (code == _URC_NO_REASON); + + uw_update_context (context, &fs); +} + +static void _Unwind_DebugHook (void *, void *) + __attribute__ ((__noinline__, __used__, __noclone__)); + +/* This function is called during unwinding. It is intended as a hook + for a debugger to intercept exceptions. CFA is the CFA of the + target frame. HANDLER is the PC to which control will be + transferred. */ +static void +_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), + void *handler __attribute__ ((__unused__))) +{ + /* We only want to use stap probes starting with v3. Earlier + versions added too much startup cost. */ +#if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3 + STAP_PROBE2 (libgcc, unwind, cfa, handler); +#else + asm (""); +#endif +} + + +/* Other platforms probably manage to do without `__attribute__ ((noreturn))' + because `uw_install_context()' is implemented as a _macro_ containing + `__builtin_eh_return ()' at the end. Without that one would obtain compiler + warnings on returning from non-void functions in `libgcc/unwind.inc' ending + with `uw_install_context ()' invocation. */ +static void __attribute__ ((noinline)) __attribute__ ((noreturn)) +uw_install_context (struct _Unwind_Context *current __attribute__ ((unused)), + struct _Unwind_Context *target) +{ + size_t i; + int res; + int old_stack_layout; + /* Reuse (hopefully) no longer needed `context->chain_stack' so as to avoid + redundant stack waste. */ +#define SET_BACKTRACE_LEN (CHAIN_STACK_CACHE_LEN * sizeof (e2k_mem_crs_t) \ + / sizeof (long)) + unsigned long *buf = (unsigned long *) target->chain_stack; + size_t level = target->level; + /* Skip return address of `syscall ()', i.e. return from it to this function + (or to `syscall ()' PLT entry in PM) in a regular way. */ + size_t extra_frames_to_skip = 1; + + /* Install register values previously set up by _Unwind_SetGR{,Ptr} ()'. */ + old_stack_layout = (__builtin_cpu_is ("elbrus-v1") + || __builtin_cpu_is ("elbrus-v2") + || __builtin_cpu_is ("elbrus-v3") + || __builtin_cpu_is ("elbrus-v4")); + + for (i = 0; i < 2; i++) + { + unsigned long long off; + int index; + size_t len; + void *p; + + if (! target->set[i]) + continue; + + p = (i == 0 ? &target->param0 : &target->param1); +#if ! defined __ptr128__ + /* Whereas in ordinary modes `%db[{0,1}]' correspond to `param{0,1}' + respectively, . . . */ + index = i; +#else /* defined __ptr128__ */ + /* . . . in PM these are `%qb[0]' and `%db[2]'. */ + index = (i == 0 ? 0 : 2); +#endif /* defined __ptr128__ */ + + len = ( +#if defined __ptr128__ + (old_stack_layout && i == 0) ? 16 + : +#endif /* defined __ptr128__ */ + 8); + + /* Take into account the layout of registers in procedure stack for + different iset versions according to C.23.1.1. */ + off = (target->psp_offset + + (old_stack_layout + ? 32 * (index >> 1) + 8 * (index & 0x1) + : 16 * index)); + + if (syshw (E2K_WRITE_PROCEDURE_STACK_EX, &off, p, len, NULL) + != 0) + abort (); + +#if defined __ptr128__ + /* With the new procedure stack layout in use we've written only the + lower half of `%qb[0]' so far. */ + if (i == 0 && len == 8) + { + off += 16; + if (syshw (E2K_WRITE_PROCEDURE_STACK_EX, &off, + (char *) p + 8, len, NULL) + != 0) + abort (); + } +#endif /* defined __ptr128__ */ + } + + /* In PM a call via PLT pushes an extra "frame" on chain stack unlike ordinary + modes. In case the address of a target function is resolved lazily during + the call, two extra frames are pushed. However, `syscall ()' must have + already been called by the time one finds himself here, therefore, exactly + one extra frame should be skipped. This lets me return from `syscall ()' + PLT entry to this function in a regular way. + + There's also an extra frame that should be skipped between syscall () and + the actual kernel entry point in QNX. */ +#if ((defined (__ptr128__) && defined SHARED) || defined (__QNX__)) + extra_frames_to_skip += 1; +#endif /* (defined (__ptr128__) && defined SHARED) || defined (__QNX__) */ + + + /* There is probably no point in returning to any of our callers, therefore + to "return" to the caller of TARGET (i.e. TARGET->ra) allocate a buffer + containing (LEVEL + 1) return addresses (keep in mind that 'LEVEL == 0' + corresponds to our current context in fact, whereas 'TARGET->level' should + be greater or equal than 1). Set the first LEVEL entries to point to a + return instruction (i.e. RET_ADDR) and the last one to 'TARGET->ra'. */ + for (i = 0; i < level; ) + { + size_t j; + + if (i == 0) + { + /* All -1 elements can be set during the first iteration of the outer + loop. */ + for (j = 0; (j < SET_BACKTRACE_LEN) && (j < level); j++) + buf[j] = -1UL; + } + else + { + j = level - i; + if (j > SET_BACKTRACE_LEN) + j = SET_BACKTRACE_LEN; + } + + if (j < SET_BACKTRACE_LEN) + { + /* It's time that we set the trailing element in BUF[] to RA. */ + buf[j++] = (unsigned long) target->ra; + } + + /* Skip `extra_frames_to_skip' frames so as to return here in a regular + way plus I elements set up at the preceding iterations. Note that + there's no point in returning to any of our callers prior to passing + control to `TARGET->ra', which is why all modifiable return addresses + except for the last one are set up to `-1'. */ + if ((res = sys_set_backtrace (buf, j, extra_frames_to_skip + i, + 0UL)) < 0) + { + perror ("set_backtrace"); + abort (); + } + + i += j; + } + + /* FIXME: currently this just lets me eliminate warnings on returning from + `noreturn' function. For E2K the underlying builtin should be expanded to + nothing and I don't even remember what its parameters mean . . . */ + __builtin_eh_return (0, target->ra); +} + +static inline +#if ! defined (__ptr128__) +_Unwind_Ptr +#else /* defined (__ptr128__) */ +/* The result of this function is used to set up `exc->private_2' which + should be capable of holding `void *stop_argument' in PM in case of + forced unwinding. */ +void * +#endif /* defined (__ptr128__) */ +uw_identify_context (struct _Unwind_Context *context) +{ + return ( +#if defined (__ptr128__) + (void *) +#endif /* defined (__ptr128__) */ + _Unwind_GetPCSP (context)); +} + +#include "unwind.inc" + +#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS) +alias (_Unwind_Backtrace); +alias (_Unwind_DeleteException); +alias (_Unwind_FindEnclosingFunction); +alias (_Unwind_ForcedUnwind); +alias (_Unwind_GetDataRelBase); +alias (_Unwind_GetTextRelBase); +alias (_Unwind_GetCFA); +alias (_Unwind_GetGR); +alias (_Unwind_GetIP); +alias (_Unwind_GetLanguageSpecificData); +alias (_Unwind_GetRegionStart); +alias (_Unwind_RaiseException); +alias (_Unwind_Resume); +alias (_Unwind_Resume_or_Rethrow); +alias (_Unwind_SetGR); +alias (_Unwind_SetIP); +#endif + +#endif /* !USING_SJLJ_EXCEPTIONS */ diff --git a/libgcc/config/sparc/crtunaligned.c b/libgcc/config/sparc/crtunaligned.c new file mode 100644 index 00000000000..8783f8ae848 --- /dev/null +++ b/libgcc/config/sparc/crtunaligned.c @@ -0,0 +1,8 @@ +#include + +static void __attribute__((constructor)) +__permit_unaligned_ldd_std (void) +{ + /* . bug #81602 */ + prctl (PR_SET_UNALIGN, PR_UNALIGN_NOPRINT, 0, 0, 0); +} diff --git a/libgcc/config/sparc/t-crtunaligned b/libgcc/config/sparc/t-crtunaligned new file mode 100644 index 00000000000..7654096c447 --- /dev/null +++ b/libgcc/config/sparc/t-crtunaligned @@ -0,0 +1,2 @@ +crtunaligned.o: $(srcdir)/config/sparc/crtunaligned.c + $(gcc_compile) -c $< diff --git a/libgcc/configure b/libgcc/configure old mode 100644 new mode 100755 diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c index 52ed6d39cc8..a08712657d7 100644 --- a/libgcc/crtstuff.c +++ b/libgcc/crtstuff.c @@ -62,6 +62,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "coretypes.h" #include "tm.h" #include "libgcc_tm.h" + +#if defined (__e2k__) && defined (__ptr128__) +/* Required because of `_Unwind_Ptr'. */ +# include "unwind.h" +#endif /* defined (__e2k__) && defined (__ptr128__) */ #include "unwind-dw2-fde.h" #ifndef FORCE_CODE_SECTION_ALIGN @@ -180,7 +185,12 @@ call_ ## FUNC (void) \ extern void __register_frame_info (const void *, struct object *) TARGET_ATTRIBUTE_WEAK; extern void __register_frame_info_bases (const void *, struct object *, - void *, void *) +# if ! (defined (__e2k__) && defined (__ptr128__)) + void *, void * +# else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr, _Unwind_Ptr +# endif /* defined (__e2k__) && defined (__ptr128__) */ + ) TARGET_ATTRIBUTE_WEAK; extern void *__deregister_frame_info (const void *) TARGET_ATTRIBUTE_WEAK; diff --git a/libgcc/libgcc-std.ver.in b/libgcc/libgcc-std.ver.in index c0a3b3eb292..a25fa998ff7 100644 --- a/libgcc/libgcc-std.ver.in +++ b/libgcc/libgcc-std.ver.in @@ -169,12 +169,14 @@ GCC_3.0 { _Unwind_GetGR _Unwind_GetIP _Unwind_GetLanguageSpecificData + _Unwind_GetPCSP _Unwind_GetRegionStart _Unwind_GetTextRelBase _Unwind_GetDataRelBase _Unwind_RaiseException _Unwind_Resume _Unwind_SetGR + _Unwind_SetGRPtr _Unwind_SetIP __deregister_frame __deregister_frame_info diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c index 561394e0069..49bd0320ca4 100644 --- a/libgcc/unwind-dw2-fde-dip.c +++ b/libgcc/unwind-dw2-fde-dip.c @@ -32,8 +32,10 @@ #include "tconfig.h" #include "tsystem.h" -#if !defined(inhibit_libc) && !defined(__OpenBSD__) +#if !defined(inhibit_libc) && !defined(__OpenBSD__) && !defined(__QNX__) #include /* Get DT_CONFIG. */ +#elif defined(__QNX__) +#include #endif #include "coretypes.h" #include "tm.h" @@ -87,10 +89,20 @@ #include #ifndef __RELOC_POINTER -# define __RELOC_POINTER(ptr, base) ((ptr) + (base)) +# if ! (defined (__e2k__) && defined (__ptr128__)) +# define __RELOC_POINTER(ptr, base) ((ptr) + (base)) +# else /* defined (__e2k__) && defined (__ptr128__) */ +// # define __RELOC_POINTER(idx, ap) &ap[idx] +# endif /* defined (__e2k__) && defined (__ptr128__) */ #endif -static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases); +static const fde * _Unwind_Find_registered_FDE ( +#if ! (defined (__e2k__) && defined ( __ptr128__)) + void *pc, +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc, +#endif /* defined (__e2k__) && defined (__ptr128__) */ + struct dwarf_eh_bases *bases); #define _Unwind_Find_FDE _Unwind_Find_registered_FDE #include "unwind-dw2-fde.c" @@ -103,8 +115,13 @@ static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases struct unw_eh_callback_data { _Unwind_Ptr pc; +#if ! (defined (__e2k__) && defined (__ptr128__)) void *tbase; void *dbase; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr tbase; + _Unwind_Ptr dbase; +#endif /* defined (__e2k__) && defined (__ptr128__) */ void *func; const fde *ret; int check_cache; @@ -127,9 +144,18 @@ static struct frame_hdr_cache_element #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__ struct elf32_fdpic_loadaddr load_base; #else +#if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Ptr load_base; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr text_base; + const char *gd; +#endif /* defined (__e2k__) && defined (__ptr128__) */ #endif +#if ! (defined (__e2k__) && defined (__ptr128__)) const ElfW(Phdr) *p_eh_frame_hdr; +#else /* defined (__e2k__) && defined (__ptr128__) */ + const struct unw_eh_frame_hdr *eh_frame_hdr_contents; +#endif /* defined (__e2k__) && defined (__ptr128__) */ const ElfW(Phdr) *p_dynamic; struct frame_hdr_cache_element *link; } frame_hdr_cache[FRAME_HDR_CACHE_SIZE]; @@ -161,26 +187,187 @@ base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data) } } +#if defined __e2k__ && defined __ptr128__ + +static unsigned int +get_range_num (const char *gd, + unsigned int phnum, + const ElfW(Phdr) *phdrs) +{ + unsigned int i = 0; + const ElfW(Phdr) *phdr; + + for (phdr = &phdrs[0]; phdr < &phdrs[phnum]; phdr++) + { + if (phdr->p_type == PT_LOAD) + { + ++i; + /* Use the same criterium as in glibc to distinguish between legacy + and packed PM ELFs. */ + if (phdr->p_offset == 0 && !(phdr->p_flags & PF_X)) + { + uintptr_t phdr_offset = (uintptr_t) phdrs - (uintptr_t) gd; + if (phdr_offset >= phdr->p_vaddr) + /* Good chances are that this is a legacy PM ELF. */ + return 0; + } + } + } + + return i; +} + +struct range +{ + uintptr_t min; + uintptr_t max; + uintptr_t align; + long delta; + int in_cud; +}; + +static void +fill_ranges (unsigned int phnum, + const ElfW(Phdr) *phdrs, + unsigned int range_num, + struct range *ranges) +{ + unsigned int i; + const ElfW(Phdr) *phdr; + + for (phdr = phdrs, i = 0; + (phdr < &phdrs[phnum] + /* Just to be on the safe side. */ + && i < range_num); + ++phdr) + { + if (phdr->p_type == PT_LOAD) + { + ranges[i].min = phdr->p_vaddr; + ranges[i].max = phdr->p_vaddr + phdr->p_memsz; + ranges[i].align = phdr->p_align; + ranges[i].in_cud = (phdr->p_flags & PF_X) ? 1 : 0; + i++; + } + } + + /* Stupidly sort the obtained ranges. I believe that qsort () may be + unavailable in context of ld.so */ + for (i = 0; i < range_num - 1; i++) + { + unsigned int j; + for (j = i + 1; j < range_num; j++) + { + if (ranges[j].min < ranges[i].min) + { + struct range tmp = ranges[i]; + ranges[i] = ranges[j]; + ranges[j] = tmp; + } + } + } + + uintptr_t max_page_aligned = 0; + uintptr_t cud_size = 0, gd_size = 0; + + for (i = 0; i < range_num; i++) + { + uintptr_t min_page_aligned = ranges[i].min & ~(ranges[i].align - 1); + uintptr_t b, r, pos; + + /* MAX_PAGE_ALIGNED corresponds to the preceding segment in this + comparison, of course. */ + if (min_page_aligned < max_page_aligned) + { + /* The Kernel should have failed to load this executable + in such a case. */ + } + + max_page_aligned = (ranges[i].max + 0xfffULL) & ~(0xfffULL); + + if (ranges[i].in_cud) + pos = cud_size; + else + pos = gd_size; + + pos = (pos + 0xfffULL) & ~0xfffULL; + r = ranges[i].min & (ranges[i].align - 1); + b = (pos + ranges[i].align - (r + 1)) / ranges[i].align; + pos = b * ranges[i].align + r; + + ranges[i].delta = pos - ranges[i].min; + pos += ranges[i].max - ranges[i].min; + + if (ranges[i].in_cud) + cud_size = pos; + else + gd_size = pos; + } +} + +long +get_offset_delta (const char *gd, + unsigned int phnum, + const ElfW(Phdr) *phdrs, + uintptr_t off) +{ + unsigned int range_num = get_range_num (gd, phnum, phdrs); + struct range ranges[range_num]; + fill_ranges (phnum, phdrs, range_num, ranges); + unsigned int j; + + for (j = 0; j < range_num; j++) + { + if (off >= ranges[j].min && off < ranges[j].max) + return ranges[j].delta; + } + + return 0; +} + +#endif /* defined __e2k__ && defined __ptr128__ */ + static int _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) { struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr; - const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic; + const ElfW(Phdr) *phdr; +# if ! (defined (__e2k__) && defined (__ptr128__)) + const ElfW(Phdr) *p_eh_frame_hdr; +#endif /* ! (defined (__e2k__) && defined (__ptr128__)) */ + const ElfW(Phdr) *p_dynamic; long n, match; #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__ struct elf32_fdpic_loadaddr load_base; #else + +# if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Ptr load_base; +# else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr text_base; + const char *gd; +# endif /* defined (__e2k__) && defined (__ptr128__) */ #endif const unsigned char *p; const struct unw_eh_frame_hdr *hdr; + +#if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Ptr eh_frame; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr eh_frame_off; + void *eh_frame; +#endif /* defined (__e2k__) && defined (__ptr128__) */ struct object ob; _Unwind_Ptr pc_low = 0, pc_high = 0; struct ext_dl_phdr_info { ElfW(Addr) dlpi_addr; + +#if defined (__e2k__) && defined (__ptr128__) + const char *dlpi_gd; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + const char *dlpi_name; const ElfW(Phdr) *dlpi_phdr; ElfW(Half) dlpi_phnum; @@ -190,8 +377,14 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) match = 0; phdr = info->dlpi_phdr; +#if ! (defined (__e2k__) && defined (__ptr128__)) load_base = info->dlpi_addr; p_eh_frame_hdr = NULL; +#else /* defined (__e2k__) && defined (__ptr128__) */ + text_base = info->dlpi_addr; + gd = info->dlpi_gd; + hdr = NULL; +#endif /* defined (__e2k__) && defined (__ptr128__) */ p_dynamic = NULL; struct frame_hdr_cache_element *prev_cache_entry = NULL, @@ -222,8 +415,14 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) if (data->pc >= cache_entry->pc_low && data->pc < cache_entry->pc_high) { +#if ! (defined (__e2k__) && defined (__ptr128__)) load_base = cache_entry->load_base; p_eh_frame_hdr = cache_entry->p_eh_frame_hdr; +#else /* defined (__e2k__) && defined (__ptr128__) */ + text_base = cache_entry->text_base; + gd = cache_entry->gd; + hdr = cache_entry->eh_frame_hdr_contents; +#endif /* defined (__e2k__) && defined (__ptr128__) */ p_dynamic = cache_entry->p_dynamic; /* And move the entry we're using to the head. */ @@ -272,10 +471,25 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) segment at the same time. */ for (n = info->dlpi_phnum; --n >= 0; phdr++) { - if (phdr->p_type == PT_LOAD) + if (phdr->p_type == PT_LOAD +#if defined (__e2k__) && defined (__ptr128__) + /* Ensure that the segment under consideration belongs to the text + segment in PM. Otherwise, the calculation of VADDR below won't + make any sense. */ + && (phdr->p_flags & PF_X) +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { +#if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Ptr vaddr = (_Unwind_Ptr) __RELOC_POINTER (phdr->p_vaddr, load_base); +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr vaddr = (text_base + phdr->p_vaddr + + get_offset_delta (info->dlpi_gd, + info->dlpi_phnum, + info->dlpi_phdr, + phdr->p_vaddr)); +#endif /* defined (__e2k__) && defined (__ptr128__) */ if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz) { match = 1; @@ -284,7 +498,22 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) } } else if (phdr->p_type == PT_GNU_EH_FRAME) - p_eh_frame_hdr = phdr; + { +#if ! (defined (__e2k__) && defined (__ptr128__)) + p_eh_frame_hdr = phdr; +#else /* defined (__e2k__) && defined (__ptr128__) */ + /* One finds himself here if the matching hash entry does not exist + yet. So, gd should still contain info->dlpi_gd set in the very + beginning of this function. */ + gcc_assert (gd == info->dlpi_gd); + hdr = ((const struct unw_eh_frame_hdr *) + &gd[phdr->p_vaddr + + get_offset_delta (gd, + info->dlpi_phnum, + info->dlpi_phdr, + phdr->p_vaddr)]); +#endif /* defined (__e2k__) && defined (__ptr128__) */ + } #ifdef PT_SUNW_UNWIND /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well. */ @@ -310,8 +539,15 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) frame_hdr_cache_head = last_cache_entry; } +#if ! (defined (__e2k__) && defined (__ptr128__)) frame_hdr_cache_head->load_base = load_base; frame_hdr_cache_head->p_eh_frame_hdr = p_eh_frame_hdr; +#else /* defined (__e2k__) && defined (__ptr128__) */ + frame_hdr_cache_head->text_base = text_base; + frame_hdr_cache_head->gd = gd; + frame_hdr_cache_head->eh_frame_hdr_contents = hdr; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + frame_hdr_cache_head->p_dynamic = p_dynamic; frame_hdr_cache_head->pc_low = pc_low; frame_hdr_cache_head->pc_high = pc_high; @@ -319,12 +555,22 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) found: - if (!p_eh_frame_hdr) + if ( +#if ! (defined (__e2k__) && defined (__ptr128__)) + !p_eh_frame_hdr +#else /* defined (__e2k__) && defined (__ptr128__) */ + !hdr +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) return 0; /* Read .eh_frame_hdr header. */ +#if ! (defined (__e2k__) && defined (__ptr128__)) hdr = (const struct unw_eh_frame_hdr *) __RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base); +#else /* defined (__e2k__) && defined (__ptr128__) */ + /* In PM it has already been read or fetched from the cache above. */ +#endif /* defined (__e2k__) && defined (__ptr128__) */ if (hdr->version != 1) return 1; @@ -341,13 +587,13 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) if (dyn->d_tag == DT_PLTGOT) { data->dbase = (void *) dyn->d_un.d_ptr; -#if defined __linux__ +# if defined __linux__ /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has relocated it. */ -#elif defined __sun__ && defined __svr4__ +# elif defined __sun__ && defined __svr4__ /* On Solaris 2/x86, we need to do this ourselves. */ data->dbase += load_base; -#endif +# endif break; } } @@ -362,7 +608,18 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) base_from_cb_data (hdr->eh_frame_ptr_enc, data), (const unsigned char *) (hdr + 1), - &eh_frame); +#if ! (defined (__e2k__) && defined (__ptr128__)) + &eh_frame +#else /* defined (__e2k__) && defined (__ptr128__) */ + &eh_frame_off +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); + +#if defined (__e2k__) && defined (__ptr128__) + eh_frame = (void *) &info->dlpi_gd[eh_frame_off - (_Unwind_Ptr) info->dlpi_gd]; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + + /* We require here specific table encoding to speed things up. Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start @@ -392,6 +649,16 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) unsigned int f_enc, f_enc_size; _Unwind_Ptr range; +#if defined (__e2k__) && defined (__ptr128__) + /* This rather strangely named variable is used by them both to + evaluate runtime PCs based on the values encoded in the `table[]' + and the pointer to the resulting FDE. In PM it's used only for the + former goal, whereas FDE is obtained via the offset from the start + of `.eh_frame_hdr' pointed to by `hdr' without this idiotic + intermediate cast to `_Unwind_Ptr'. */ + data_base += text_base - (_Unwind_Ptr) gd; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + mid = fde_count - 1; if (data->pc < table[0].initial_loc + data_base) return 1; @@ -413,8 +680,11 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) gcc_assert (lo < hi); } - +#if ! (defined (__e2k__) && defined (__ptr128__)) f = (fde *) (table[mid].fde + data_base); +#else /* defined (__e2k__) && defined (__ptr128__) */ + f = (fde *) &((char *) hdr)[table[mid].fde]; +#endif /* defined (__e2k__) && defined (__ptr128__) */ f_enc = get_fde_encoding (f); f_enc_size = size_of_encoded_value (f_enc); read_encoded_value_with_base (f_enc & 0x0f, 0, @@ -429,13 +699,21 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) /* We have no sorted search table, so need to go the slow way. As soon as GLIBC will provide API so to notify that a library has been removed, we could cache this (and thus use search_object). */ +#if ! (defined (__e2k__) && defined (__ptr128__)) ob.pc_begin = NULL; +#else /* defined (__e2k__) && defined (__ptr128__) */ + ob.pc_begin = 0; +#endif /* defined (__e2k__) && defined (__ptr128__) */ ob.tbase = data->tbase; ob.dbase = data->dbase; ob.u.single = (fde *) eh_frame; ob.s.i = 0; ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */ - data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc); + data->ret = linear_search_fdes (&ob, (fde *) eh_frame, +#if !(defined (__e2k__) && defined (__ptr128__)) + (void *) +#endif /* !(defined (__e2k__) && defined (__ptr128__)) */ + data->pc); if (data->ret != NULL) { _Unwind_Ptr func; @@ -450,7 +728,13 @@ _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) } const fde * -_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) +_Unwind_Find_FDE ( +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc, +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc, +#endif /* defined (__e2k__) && defined (__ptr128__) */ + struct dwarf_eh_bases *bases) { struct unw_eh_callback_data data; const fde *ret; @@ -460,8 +744,13 @@ _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) return ret; data.pc = (_Unwind_Ptr) pc; +#if ! (defined (__e2k__) && defined (__ptr128__)) data.tbase = NULL; data.dbase = NULL; +#else /* defined (__e2k__) && defined (__ptr128__) */ + data.tbase = 0; + data.dbase = 0; +#endif /* defined (__e2k__) && defined (__ptr128__) */ data.func = NULL; data.ret = NULL; data.check_cache = 1; diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c index 02b588de892..7667e73b150 100644 --- a/libgcc/unwind-dw2-fde.c +++ b/libgcc/unwind-dw2-fde.c @@ -83,13 +83,22 @@ static __gthread_mutex_t object_mutex; void __register_frame_info_bases (const void *begin, struct object *ob, - void *tbase, void *dbase) +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *tbase, void *dbase +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr tbase, _Unwind_Ptr dbase +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { /* If .eh_frame is empty, don't register at all. */ if ((const uword *) begin == 0 || *(const uword *) begin == 0) return; +#if ! (defined (__e2k__) && defined (__ptr128__)) ob->pc_begin = (void *)-1; +#else /* defined (__e2k__) && defined (__ptr128__) */ + ob->pc_begin = (_Unwind_Ptr) -1; +#endif /* defined (__e2k__) && defined (__ptr128__) */ ob->tbase = tbase; ob->dbase = dbase; ob->u.single = begin; @@ -121,7 +130,31 @@ __register_frame_info_bases (const void *begin, struct object *ob, void __register_frame_info (const void *begin, struct object *ob) { - __register_frame_info_bases (begin, ob, 0, 0); +#if defined (__e2k__) && defined (__ptr128__) + _Unwind_Ptr tbase; + _Unwind_Ptr dbase; + + tbase = ({ + register unsigned long cud; + asm volatile ("rrd %%cud.lo, %0" : "=r" (cud)); + (_Unwind_Ptr) (cud & 0xffffffff); + }); + + dbase = ({ + register unsigned long gd; + asm volatile ("rrd %%gd.lo, %0" : "=r" (gd)); + (_Unwind_Ptr) (gd & 0xffffffff); + }); +#endif /* defined (__e2k__) && defined (__ptr128__) */ + + __register_frame_info_bases (begin, ob, +#if ! (defined (__e2k__) && defined (__ptr128__)) + 0, 0 +#else /* defined (__e2k__) && defined (__ptr128__) */ + tbase, dbase +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); + } void @@ -143,9 +176,18 @@ __register_frame (void *begin) void __register_frame_info_table_bases (void *begin, struct object *ob, - void *tbase, void *dbase) +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *tbase, void *dbase +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr tbase, _Unwind_Ptr dbase +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { +#if ! (defined (__e2k__) && defined (__ptr128__)) ob->pc_begin = (void *)-1; +#else /* defined (__e2k__) && defined (__ptr128__) */ + ob->pc_begin = (_Unwind_Ptr) -1; +#endif /* defined (__e2k__) && defined (__ptr128__) */ ob->tbase = tbase; ob->dbase = dbase; ob->u.array = begin; @@ -272,10 +314,20 @@ base_from_object (unsigned char encoding, struct object *ob) switch (encoding & 0x70) { case DW_EH_PE_absptr: +#if ! (defined (__e2k__) && defined (__ptr128__)) case DW_EH_PE_pcrel: +#endif /* ! (defined (__e2k__) && defined (__ptr128__)) */ case DW_EH_PE_aligned: return 0; +#if defined (__e2k__) && defined (__ptr128__) + case DW_EH_PE_pcrel: + /* Take into account that in PM the value calculated by means of the + relative encoding and the current position in `.eh_frame' belong to + different segments. */ + return (_Unwind_Ptr) ob->tbase - (_Unwind_Ptr) ob->dbase; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + case DW_EH_PE_textrel: return (_Unwind_Ptr) ob->tbase; case DW_EH_PE_datarel: @@ -292,7 +344,11 @@ static int get_cie_encoding (const struct dwarf_cie *cie) { const unsigned char *aug, *p; +#if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Ptr dummy; +#else /* defined (__e2k__) && defined (__ptr128__) */ + void *dummy; +#endif /* defined (__e2k__) && defined (__ptr128__) */ _uleb128_t utmp; _sleb128_t stmp; @@ -329,7 +385,13 @@ get_cie_encoding (const struct dwarf_cie *cie) /* ??? Avoid dereferencing indirect pointers, since we're faking the base address. Gotta keep DW_EH_PE_aligned intact, however. */ - p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy); + p = +#if ! (defined (__e2k__) && defined (__ptr128__)) + read_encoded_value_with_base +#else /* defined (__e2k__) && defined (__ptr128__) */ + read_encoded_ptr_with_base +#endif /* defined (__e2k__) && defined (__ptr128__) */ + (*p & 0x7F, 0, p + 1, &dummy); } /* LSDA encoding. */ else if (*aug == 'L') @@ -671,17 +733,30 @@ classify_object_over_fdes (struct object *ob, const fde *this_fde) the encoding is smaller than a pointer a true NULL may not be representable. Assume 0 in the representable bits is NULL. */ mask = size_of_encoded_value (encoding); + + /* FIXME: in PM `size_of_encoded_value ()' returns 8, which is probably + unreasonably large and should be fixed. This makes the calculations + below result in an unexpected `mask == 0' somehow taking into account + that `_Unwind_Ptr' is a 32-bit type. Temporarely overcome this issue + this way . . . */ +#if ! (defined (__e2k__) && defined (__ptr128__)) if (mask < sizeof (void *)) mask = (((_Unwind_Ptr) 1) << (mask << 3)) - 1; else +#endif /* ! (defined (__e2k__) && defined (__ptr128__)) */ mask = -1; if ((pc_begin & mask) == 0) continue; count += 1; +#if ! (defined (__e2k__) && defined (__ptr128__)) if ((void *) pc_begin < ob->pc_begin) ob->pc_begin = (void *) pc_begin; +#else /* defined (__e2k__) && defined (__ptr128__) */ + if (pc_begin < ob->pc_begin) + ob->pc_begin = pc_begin; +#endif /* defined (__e2k__) && defined (__ptr128__) */ } return count; @@ -733,10 +808,14 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, const fde *this_fde) In these cases, the function address will be NULL, but if the encoding is smaller than a pointer a true NULL may not be representable. Assume 0 in the representable bits is NULL. */ + mask = size_of_encoded_value (encoding); + /* See above. */ +#if ! (defined (__e2k__) && defined (__ptr128__)) if (mask < sizeof (void *)) mask = (((_Unwind_Ptr) 1) << (mask << 3)) - 1; else +#endif /* defined (__e2k__) && defined (__ptr128__) */ mask = -1; if ((pc_begin & mask) == 0) @@ -823,7 +902,13 @@ init_object (struct object* ob) array. */ static const fde * -linear_search_fdes (struct object *ob, const fde *this_fde, void *pc) +linear_search_fdes (struct object *ob, const fde *this_fde, +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { const struct dwarf_cie *last_cie = 0; int encoding = ob->s.b.encoding; @@ -893,7 +978,13 @@ linear_search_fdes (struct object *ob, const fde *this_fde, void *pc) implementations of increasing complexity. */ static inline const fde * -binary_search_unencoded_fdes (struct object *ob, void *pc) +binary_search_unencoded_fdes (struct object *ob, +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { struct fde_vector *vec = ob->u.sort; size_t lo, hi; @@ -902,9 +993,19 @@ binary_search_unencoded_fdes (struct object *ob, void *pc) { size_t i = (lo + hi) / 2; const fde *const f = vec->array[i]; +#if ! (defined (__e2k__) && defined (__ptr128__)) void *pc_begin; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc_begin; +#endif /* defined (__e2k__) && defined (__ptr128__) */ uaddr pc_range; - memcpy (&pc_begin, (const void * const *) f->pc_begin, sizeof (void *)); + memcpy (&pc_begin, +#if ! (defined (__e2k__) && defined (__ptr128__)) + (const void * const *) f->pc_begin, sizeof (void *) +#else /* defined (__e2k__) && defined (__ptr128__) */ + (const _Unwind_Ptr *) f->pc_begin, sizeof (_Unwind_Ptr) +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); memcpy (&pc_range, (const uaddr *) f->pc_begin + 1, sizeof (uaddr)); if (pc < pc_begin) @@ -919,7 +1020,13 @@ binary_search_unencoded_fdes (struct object *ob, void *pc) } static inline const fde * -binary_search_single_encoding_fdes (struct object *ob, void *pc) +binary_search_single_encoding_fdes (struct object *ob, +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { struct fde_vector *vec = ob->u.sort; int encoding = ob->s.b.encoding; @@ -949,7 +1056,13 @@ binary_search_single_encoding_fdes (struct object *ob, void *pc) } static inline const fde * -binary_search_mixed_encoding_fdes (struct object *ob, void *pc) +binary_search_mixed_encoding_fdes (struct object *ob, +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { struct fde_vector *vec = ob->u.sort; size_t lo, hi; @@ -980,7 +1093,13 @@ binary_search_mixed_encoding_fdes (struct object *ob, void *pc) } static const fde * -search_object (struct object* ob, void *pc) +search_object (struct object* ob, +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { /* If the data hasn't been sorted, try to do this now. We may have more memory available than last time we tried. */ @@ -1024,7 +1143,13 @@ search_object (struct object* ob, void *pc) } const fde * -_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases) +_Unwind_Find_FDE ( +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc, +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc, +#endif /* defined (__e2k__) && defined (__ptr128__) */ + struct dwarf_eh_bases *bases) { struct object *ob; const fde *f = NULL; diff --git a/libgcc/unwind-dw2-fde.h b/libgcc/unwind-dw2-fde.h index 7141867260c..4d7a0a6cd4f 100644 --- a/libgcc/unwind-dw2-fde.h +++ b/libgcc/unwind-dw2-fde.h @@ -39,9 +39,15 @@ struct fde_vector struct object { +#if ! (defined (__e2k__) && defined (__ptr128__)) void *pc_begin; void *tbase; void *dbase; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc_begin; + _Unwind_Ptr tbase; + _Unwind_Ptr dbase; +#endif /* defined (__e2k__) && defined (__ptr128__) */ union { const struct dwarf_fde *single; struct dwarf_fde **array; @@ -84,18 +90,33 @@ struct old_object struct dwarf_eh_bases { +#if ! (defined (__e2k__) && defined (__ptr128__)) void *tbase; void *dbase; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr tbase; + _Unwind_Ptr dbase; +#endif /* defined (__e2k__) && defined (__ptr128__) */ void *func; }; extern void __register_frame_info_bases (const void *, struct object *, - void *, void *); +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *, void * +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr, _Unwind_Ptr +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); extern void __register_frame_info (const void *, struct object *); extern void __register_frame (void *); extern void __register_frame_info_table_bases (void *, struct object *, - void *, void *); +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *, void * +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr, _Unwind_Ptr +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); extern void __register_frame_info_table (void *, struct object *); extern void __register_frame_table (void *); extern void *__deregister_frame_info (const void *); @@ -105,7 +126,11 @@ extern void __deregister_frame (void *); typedef int sword __attribute__ ((mode (SI))); typedef unsigned int uword __attribute__ ((mode (SI))); -typedef unsigned int uaddr __attribute__ ((mode (pointer))); +typedef unsigned int uaddr +#if ! (defined (__e2k__) && defined (__ptr128__)) +__attribute__ ((mode (pointer))) +#endif /* ! (defined (__e2k__) && defined (__ptr128__)) */ + ; typedef int saddr __attribute__ ((mode (pointer))); typedef unsigned char ubyte; @@ -163,7 +188,13 @@ next_fde (const fde *f) return (const fde *) ((const char *) f + f->length + sizeof (f->length)); } -extern const fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *); +extern const fde * _Unwind_Find_FDE ( +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *, +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr, +#endif /* defined (__e2k__) && defined (__ptr128__) */ + struct dwarf_eh_bases *); static inline int last_fde (struct object *obj __attribute__ ((__unused__)), const fde *f) diff --git a/libgcc/unwind-dw2.h b/libgcc/unwind-dw2.h index df048e45414..a40bfc36fce 100644 --- a/libgcc/unwind-dw2.h +++ b/libgcc/unwind-dw2.h @@ -31,6 +31,8 @@ typedef struct another register, or a location expression. */ struct frame_state_reg_info { + /* reg[] isn't currently used in any way on E2K. */ +#if ! defined __e2k__ struct { union { _Unwind_Word reg; @@ -47,6 +49,7 @@ typedef struct REG_UNDEFINED } how; } reg[__LIBGCC_DWARF_FRAME_REGISTERS__+1]; +#endif /* ! defined __e2k__ */ /* Used to implement DW_CFA_remember_state. */ struct frame_state_reg_info *prev; diff --git a/libgcc/unwind-generic.h b/libgcc/unwind-generic.h index 77dd5a90202..5768b33bf58 100644 --- a/libgcc/unwind-generic.h +++ b/libgcc/unwind-generic.h @@ -49,10 +49,17 @@ typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__))); typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__))); #if defined(__ia64__) && defined(__hpux__) typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__))); -#else +#elif ! (defined (__e2k__) && defined (__ptr128__)) typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); #endif + +#if ! (defined (__e2k__) && defined (__ptr128__)) typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); +#else /* defined (__e2k__) && defined (__ptr128__) */ + /* We may live in 64-bit address space in PM nowadays if ELF64 is used. */ +typedef unsigned long _Unwind_Ptr; +typedef unsigned long _Unwind_Internal_Ptr; +#endif /* defined (__e2k__) && defined (__ptr128__) */ /* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and consumer of an exception. We'll go along with this for now even on @@ -95,8 +102,13 @@ struct _Unwind_Exception #if !defined (__USING_SJLJ_EXCEPTIONS__) && defined (__SEH__) _Unwind_Word private_[6]; #else +# if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Word private_1; _Unwind_Word private_2; +# else /* defined (__e2k__) && defined (__ptr128__) */ + void *private_1; + void *private_2; +# endif /* defined (__e2k__) && defined (__ptr128__) */ #endif /* @@@ The IA-64 ABI says that this structure must be double-word aligned. @@ -170,6 +182,12 @@ _Unwind_Backtrace (_Unwind_Trace_Fn, void *); extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int); extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + /* This one should be externally visible only in Protected Mode. */ +#if defined (__e2k__) && defined (__ptr128__) +extern void _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, + void *p); +#endif /* defined (__e2k__) && defined (__ptr128__) */ + extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *); extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); @@ -244,7 +262,13 @@ extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *); /* @@@ Given an address, return the entry point of the function that contains it. */ -extern void * _Unwind_FindEnclosingFunction (void *pc); +extern void * _Unwind_FindEnclosingFunction ( +#if ! (defined (__e2k__) && defined (__ptr128__)) + void *pc +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr pc +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ); #ifndef __SIZEOF_LONG__ #error "__SIZEOF_LONG__ macro not defined" @@ -269,6 +293,9 @@ extern void * _Unwind_FindEnclosingFunction (void *pc); #elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__ typedef long long _sleb128_t; typedef unsigned long long _uleb128_t; +#elif defined (__e2k__) && defined (__ptr128__) + typedef long _sleb128_t; + typedef unsigned long _uleb128_t; #else # error "What type shall we use for _sleb128_t?" #endif diff --git a/libgcc/unwind-pe.h b/libgcc/unwind-pe.h index 194ca0aa6d0..e342318c159 100644 --- a/libgcc/unwind-pe.h +++ b/libgcc/unwind-pe.h @@ -71,6 +71,11 @@ size_of_encoded_value (unsigned char encoding) __attribute__ ((unused)); static unsigned int size_of_encoded_value (unsigned char encoding) { +#if defined (__e2k__) && defined (__ptr128__) + if (encoding == DW_EH_PE_aligned) + return 16; +#endif /* defined (__e2k__) && defined (__ptr128__) */ + if (encoding == DW_EH_PE_omit) return 0; @@ -179,11 +184,19 @@ read_sleb128 (const unsigned char *p, _sleb128_t *val) static const unsigned char * read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, - const unsigned char *p, _Unwind_Ptr *val) + const unsigned char *p, _Unwind_Ptr *val +#if defined (__e2k__) && defined (__ptr128__) + , void **pval +#endif /* defined (__e2k__) && defined (__ptr128__) */ + ) { union unaligned { +#if ! (defined (__e2k__) && defined (__ptr128__)) void *ptr; +#else /* (defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Ptr ptr; +#endif /* (defined (__e2k__) && defined (__ptr128__) */ unsigned u2 __attribute__ ((mode (HI))); unsigned u4 __attribute__ ((mode (SI))); unsigned u8 __attribute__ ((mode (DI))); @@ -199,8 +212,17 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, { _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p; a = (a + sizeof (void *) - 1) & - sizeof(void *); +#if ! (defined (__e2k__) && defined (__ptr128__)) result = *(_Unwind_Internal_Ptr *) a; p = (const unsigned char *) (_Unwind_Internal_Ptr) (a + sizeof (void *)); +#else /* defined (__e2k__) && defined (__ptr128__) */ + /* Do without conversion of an integer into a pointer when calculating an + aligned pointer in PM. */ + p += a - (_Unwind_Internal_Ptr) p; + result = *(_Unwind_Internal_Ptr *) (void *) p; + *pval = *(void **) (void *) p; + p += sizeof (void *); +#endif /* defined (__e2k__) && defined (__ptr128__) */ } else { @@ -208,7 +230,11 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, { case DW_EH_PE_absptr: result = (_Unwind_Internal_Ptr) u->ptr; +#if ! (defined (__e2k__) && defined (__ptr128__)) p += sizeof (void *); +#else /* defined (__e2k__) && defined (__ptr128__) */ + p += sizeof (_Unwind_Ptr); +#endif /* defined (__e2k__) && defined (__ptr128__) */ break; case DW_EH_PE_uleb128: @@ -261,15 +287,56 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base, { result += ((encoding & 0x70) == DW_EH_PE_pcrel ? (_Unwind_Internal_Ptr) u : base); +#if defined (__e2k__) && defined (__ptr128__) + /* In Protected Mode U belongs to the data segment, while PC, + being evaluated by means of DW_EH_PE_pcrel, to the text one. + BASE takes into account the difference between the bases of + these segments. */ + if ((encoding & 0x70) == DW_EH_PE_pcrel) + result += base; +#endif /* defined (__e2k__) && defined (__ptr128__) */ if (encoding & DW_EH_PE_indirect) result = *(_Unwind_Internal_Ptr *) result; } } +#if defined (__e2k__) && defined (__ptr128__) + /* In PM VAL is of an inappropriate type for returning a pointer, which + is why the user may pass NULL for it. */ + if (val) +#endif /* defined (__e2k__) && defined (__ptr128__) */ *val = result; return p; } +#if defined (__e2k__) && defined (__ptr128__) + +static const unsigned char * +read_encoded_ptr_with_base (unsigned char encoding, _Unwind_Ptr base, + const unsigned char *p, void **pval) +{ + return read_encoded_value_with_base (encoding, + base, p, NULL, pval); +} + + +# ifndef NO_BASE_OF_ENCODED_VALUE +static inline const unsigned char * +read_encoded_ptr (struct _Unwind_Context *context, unsigned char encoding, + const unsigned char *p, void **pval) +{ + return read_encoded_ptr_with_base (encoding, + base_of_encoded_value (encoding, context), + p, pval); +} +# endif /* ! defined NO_BASE_OF_ENCODED_VALUE */ + +# define read_encoded_value_with_base(a, b, c, d) \ + read_encoded_value_with_base (a, b, c, d, NULL) + +#endif /* defined (__e2k__) && defined (__ptr128__) */ + + #ifndef NO_BASE_OF_ENCODED_VALUE /* Like read_encoded_value_with_base, but get the base from the context diff --git a/libgcc/unwind.inc b/libgcc/unwind.inc index 658bd94f8f3..bc3bd12bcc9 100644 --- a/libgcc/unwind.inc +++ b/libgcc/unwind.inc @@ -83,9 +83,16 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) { struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; +#if defined __e2k__ + e2k_mem_crs_t chain_stack[CHAIN_STACK_CACHE_LEN]; +#endif /* defined __e2k__ */ /* Set up this_context to describe the current stack frame. */ - uw_init_context (&this_context); + uw_init_context (&this_context +#if defined __e2k__ + , chain_stack +#endif /* defined __e2k__ */ + ); cur_context = this_context; /* Phase 1: Search. Unwind the stack, calling the personality routine @@ -127,6 +134,13 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc) exc->private_1 = 0; exc->private_2 = uw_identify_context (&cur_context); +#if defined __e2k__ + /* Now that the chain stack cache is shared between `{THIS,CUR}_CONTEXT' it + may have been changed while updating the latter above. Ensure that it + matches THIS_CONTEXT prior to starting phase 2. */ + reinit_chain_stack_cache (&this_context); +#endif /* defined __e2k__ */ + cur_context = this_context; code = _Unwind_RaiseException_Phase2 (exc, &cur_context); if (code != _URC_INSTALL_CONTEXT) @@ -142,8 +156,13 @@ static _Unwind_Reason_Code _Unwind_ForcedUnwind_Phase2 (struct _Unwind_Exception *exc, struct _Unwind_Context *context) { +#if ! (defined (__e2k__) && defined (__ptr128__)) _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) (_Unwind_Ptr) exc->private_1; void *stop_argument = (void *) (_Unwind_Ptr) exc->private_2; +#else /* defined (__e2k__) && defined (__ptr128__) */ + _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exc->private_1; + void *stop_argument = exc->private_2; +#endif /* defined (__e2k__) && defined (__ptr128__) */ _Unwind_Reason_Code code, stop_code; while (1) @@ -197,12 +216,24 @@ _Unwind_ForcedUnwind (struct _Unwind_Exception *exc, { struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; +#if defined __e2k__ + e2k_mem_crs_t chain_stack[CHAIN_STACK_CACHE_LEN]; +#endif /* defined __e2k__ */ - uw_init_context (&this_context); + uw_init_context (&this_context +#if defined __e2k__ + , chain_stack +#endif /* defined __e2k__ */ + ); cur_context = this_context; +#if ! (defined (__e2k__) && defined (__ptr128__)) exc->private_1 = (_Unwind_Ptr) stop; exc->private_2 = (_Unwind_Ptr) stop_argument; +#else /* defined (__e2k__) && defined (__ptr128__) */ + exc->private_1 = (void *) stop; + exc->private_2 = stop_argument; +#endif /* defined (__e2k__) && defined (__ptr128__) */ code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); if (code != _URC_INSTALL_CONTEXT) @@ -220,8 +251,16 @@ _Unwind_Resume (struct _Unwind_Exception *exc) { struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; +#if defined __e2k__ + e2k_mem_crs_t chain_stack[CHAIN_STACK_CACHE_LEN]; +#endif /* defined __e2k__ */ - uw_init_context (&this_context); + + uw_init_context (&this_context +#if defined __e2k__ + , chain_stack +#endif /* defined __e2k__ */ + ); cur_context = this_context; /* Choose between continuing to process _Unwind_RaiseException @@ -245,13 +284,20 @@ _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc) { struct _Unwind_Context this_context, cur_context; _Unwind_Reason_Code code; +#if defined __e2k__ + e2k_mem_crs_t chain_stack[CHAIN_STACK_CACHE_LEN]; +#endif /* defined __e2k__ */ /* Choose between continuing to process _Unwind_RaiseException or _Unwind_ForcedUnwind. */ if (exc->private_1 == 0) return _Unwind_RaiseException (exc); - uw_init_context (&this_context); + uw_init_context (&this_context +#if defined __e2k__ + , chain_stack +#endif /* defined __e2k__ */ + ); cur_context = this_context; code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context); @@ -279,8 +325,15 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) { struct _Unwind_Context context; _Unwind_Reason_Code code; +#if defined __e2k__ + e2k_mem_crs_t chain_stack[CHAIN_STACK_CACHE_LEN]; +#endif /* defined __e2k__ */ - uw_init_context (&context); + uw_init_context (&context +#if defined __e2k__ + , chain_stack +#endif /* defined __e2k__ */ + ); while (1) { diff --git a/libquadmath/configure b/libquadmath/configure index d2f13bf7751..4a1b60dcfb2 100755 --- a/libquadmath/configure +++ b/libquadmath/configure @@ -7669,7 +7669,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' + lt_prog_compiler_pic='-fPIC' ;; sysv4*MP*) @@ -7796,7 +7796,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - lt_prog_compiler_pic='-fPIC -shared' + lt_prog_compiler_pic='-fPIC' ;; osf3* | osf4* | osf5*) diff --git a/libquadmath/printf/printf_fp.c b/libquadmath/printf/printf_fp.c index 8effcee88fa..0909a806529 100644 --- a/libquadmath/printf/printf_fp.c +++ b/libquadmath/printf/printf_fp.c @@ -122,6 +122,63 @@ static wchar_t *group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no, const char *grouping, wchar_t thousands_sep, int ngroups); +struct hack_digit_param +{ + /* Sign of the exponent. */ + int expsign; + /* The type of output format that will be used: 'e'/'E' or 'f'. */ + int type; + /* and the exponent. */ + int exponent; + /* The fraction of the floting-point value in question */ + MPN_VAR(frac); + /* Scaling factor. */ + MPN_VAR(scale); + /* Temporary bignum value. */ + MPN_VAR(tmp); +}; + +static wchar_t +hack_digit (struct hack_digit_param *p) +{ + mp_limb_t hi; + + if (p->expsign != 0 && p->type == 'f' && p->exponent-- > 0) + hi = 0; + else if (p->scalesize == 0) + { + hi = p->frac[p->fracsize - 1]; + p->frac[p->fracsize - 1] = mpn_mul_1 (p->frac, p->frac, p->fracsize - 1, 10); + } + else + { + if (p->fracsize < p->scalesize) + hi = 0; + else + { + hi = mpn_divmod (p->tmp, p->frac, p->fracsize, p->scale, p->scalesize); + p->tmp[p->fracsize - p->scalesize] = hi; + hi = p->tmp[0]; + + p->fracsize = p->scalesize; + while (p->fracsize != 0 && p->frac[p->fracsize - 1] == 0) + --p->fracsize; + if (p->fracsize == 0) + { + /* We're not prepared for an mpn variable with zero + limbs. */ + p->fracsize = 1; + return L_('0') + hi; + } + } + + mp_limb_t _cy = mpn_mul_1 (p->frac, p->frac, p->fracsize, 10); + if (_cy != 0) + p->frac[p->fracsize++] = _cy; + } + + return L_('0') + hi; +} int __quadmath_printf_fp (struct __quadmath_printf_file *fp, @@ -150,28 +207,14 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* We need to shift the contents of fp_input by this amount of bits. */ int to_shift = 0; - /* The fraction of the floting-point value in question */ - MPN_VAR(frac); - /* and the exponent. */ - int exponent; - /* Sign of the exponent. */ - int expsign = 0; + struct hack_digit_param p; /* Sign of float number. */ int is_neg = 0; - /* Scaling factor. */ - MPN_VAR(scale); - - /* Temporary bignum value. */ - MPN_VAR(tmp); - /* Digit which is result of last hack_digit() call. */ wchar_t last_digit, next_digit; bool more_bits; - /* The type of output format that will be used: 'e'/'E' or 'f'. */ - int type; - /* Counter for number of written characters. */ int done = 0; @@ -186,48 +229,7 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* Flag whether wbuffer is malloc'ed or not. */ int buffer_malloced = 0; - auto wchar_t hack_digit (void); - - wchar_t hack_digit (void) - { - mp_limb_t hi; - - if (expsign != 0 && type == 'f' && exponent-- > 0) - hi = 0; - else if (scalesize == 0) - { - hi = frac[fracsize - 1]; - frac[fracsize - 1] = mpn_mul_1 (frac, frac, fracsize - 1, 10); - } - else - { - if (fracsize < scalesize) - hi = 0; - else - { - hi = mpn_divmod (tmp, frac, fracsize, scale, scalesize); - tmp[fracsize - scalesize] = hi; - hi = tmp[0]; - - fracsize = scalesize; - while (fracsize != 0 && frac[fracsize - 1] == 0) - --fracsize; - if (fracsize == 0) - { - /* We're not prepared for an mpn variable with zero - limbs. */ - fracsize = 1; - return L_('0') + hi; - } - } - - mp_limb_t _cy = mpn_mul_1 (frac, frac, fracsize, 10); - if (_cy != 0) - frac[fracsize++] = _cy; - } - - return L_('0') + hi; - } + p.expsign = 0; /* Figure out the decimal point character. */ #ifdef USE_NL_LANGINFO @@ -397,11 +399,11 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, } else { - fracsize = mpn_extract_flt128 (fp_input, - (sizeof (fp_input) / - sizeof (fp_input[0])), - &exponent, &is_neg, fpnum); - to_shift = 1 + fracsize * BITS_PER_MP_LIMB - FLT128_MANT_DIG; + p.fracsize = mpn_extract_flt128 (fp_input, + (sizeof (fp_input) / + sizeof (fp_input[0])), + &p.exponent, &is_neg, fpnum); + to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - FLT128_MANT_DIG; } } @@ -437,20 +439,20 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, efficient to use variables of the fixed maximum size but because this would be really big it could lead to memory problems. */ { - mp_size_t bignum_size = ((ABS (exponent) + BITS_PER_MP_LIMB - 1) + mp_size_t bignum_size = ((ABS (p.exponent) + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB + (FLT128_MANT_DIG / BITS_PER_MP_LIMB > 2 ? 8 : 4)) * sizeof (mp_limb_t); - frac = (mp_limb_t *) alloca (bignum_size); - tmp = (mp_limb_t *) alloca (bignum_size); - scale = (mp_limb_t *) alloca (bignum_size); + p.frac = (mp_limb_t *) alloca (bignum_size); + p.tmp = (mp_limb_t *) alloca (bignum_size); + p.scale = (mp_limb_t *) alloca (bignum_size); } /* We now have to distinguish between numbers with positive and negative exponents because the method used for the one is not applicable/efficient for the other. */ - scalesize = 0; - if (exponent > 2) + p.scalesize = 0; + if (p.exponent > 2) { /* |FP| >= 8.0. */ int scaleexpo = 0; @@ -459,22 +461,22 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; int cnt_h, cnt_l, i; - if ((exponent + to_shift) % BITS_PER_MP_LIMB == 0) + if ((p.exponent + to_shift) % BITS_PER_MP_LIMB == 0) { - MPN_COPY_DECR (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, - fp_input, fracsize); - fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; + MPN_COPY_DECR (p.frac + (p.exponent + to_shift) / BITS_PER_MP_LIMB, + fp_input, p.fracsize); + p.fracsize += (p.exponent + to_shift) / BITS_PER_MP_LIMB; } else { - cy = mpn_lshift (frac + (exponent + to_shift) / BITS_PER_MP_LIMB, - fp_input, fracsize, - (exponent + to_shift) % BITS_PER_MP_LIMB); - fracsize += (exponent + to_shift) / BITS_PER_MP_LIMB; + cy = mpn_lshift (p.frac + (p.exponent + to_shift) / BITS_PER_MP_LIMB, + fp_input, p.fracsize, + (p.exponent + to_shift) % BITS_PER_MP_LIMB); + p.fracsize += (p.exponent + to_shift) / BITS_PER_MP_LIMB; if (cy) - frac[fracsize++] = cy; + p.frac[p.fracsize++] = cy; } - MPN_ZERO (frac, (exponent + to_shift) / BITS_PER_MP_LIMB); + MPN_ZERO (p.frac, (p.exponent + to_shift) / BITS_PER_MP_LIMB); assert (powers > &_fpioconst_pow10[0]); do @@ -483,9 +485,9 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* The number of the product of two binary numbers with n and m bits respectively has m+n or m+n-1 bits. */ - if (exponent >= scaleexpo + powers->p_expo - 1) + if (p.exponent >= scaleexpo + powers->p_expo - 1) { - if (scalesize == 0) + if (p.scalesize == 0) { if (FLT128_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB) { @@ -494,60 +496,60 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, - _FPIO_CONST_OFFSET) /* 64bit const offset is not enough for IEEE quad long double. */ - tmpsize = powers->arraysize + _FPIO_CONST_SHIFT; - memcpy (tmp + _FPIO_CONST_SHIFT, + p.tmpsize = powers->arraysize + _FPIO_CONST_SHIFT; + memcpy (p.tmp + _FPIO_CONST_SHIFT, &__tens[powers->arrayoff], - tmpsize * sizeof (mp_limb_t)); - MPN_ZERO (tmp, _FPIO_CONST_SHIFT); + p.tmpsize * sizeof (mp_limb_t)); + MPN_ZERO (p.tmp, _FPIO_CONST_SHIFT); /* Adjust exponent, as scaleexpo will be this much bigger too. */ - exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB; + p.exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB; } else { - tmpsize = powers->arraysize; - memcpy (tmp, &__tens[powers->arrayoff], - tmpsize * sizeof (mp_limb_t)); + p.tmpsize = powers->arraysize; + memcpy (p.tmp, &__tens[powers->arrayoff], + p.tmpsize * sizeof (mp_limb_t)); } } else { - cy = mpn_mul (tmp, scale, scalesize, + cy = mpn_mul (p.tmp, p.scale, p.scalesize, &__tens[powers->arrayoff + _FPIO_CONST_OFFSET], powers->arraysize - _FPIO_CONST_OFFSET); - tmpsize = scalesize + powers->arraysize - _FPIO_CONST_OFFSET; + p.tmpsize = p.scalesize + powers->arraysize - _FPIO_CONST_OFFSET; if (cy == 0) - --tmpsize; + --p.tmpsize; } - if (MPN_GE (frac, tmp)) + if (MPN_GE (p.frac, p.tmp)) { int cnt; - MPN_ASSIGN (scale, tmp); - count_leading_zeros (cnt, scale[scalesize - 1]); - scaleexpo = (scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1; + MPN_ASSIGN (p.scale, p.tmp); + count_leading_zeros (cnt, p.scale[p.scalesize - 1]); + scaleexpo = (p.scalesize - 2) * BITS_PER_MP_LIMB - cnt - 1; exp10 |= 1 << explog; } } --explog; } while (powers > &_fpioconst_pow10[0]); - exponent = exp10; + p.exponent = exp10; /* Optimize number representations. We want to represent the numbers with the lowest number of bytes possible without losing any bytes. Also the highest bit in the scaling factor has to be set (this is a requirement of the MPN division routines). */ - if (scalesize > 0) + if (p.scalesize > 0) { /* Determine minimum number of zero bits at the end of both numbers. */ - for (i = 0; scale[i] == 0 && frac[i] == 0; i++) + for (i = 0; p.scale[i] == 0 && p.frac[i] == 0; i++) ; /* Determine number of bits the scaling factor is misplaced. */ - count_leading_zeros (cnt_h, scale[scalesize - 1]); + count_leading_zeros (cnt_h, p.scale[p.scalesize - 1]); if (cnt_h == 0) { @@ -555,27 +557,27 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, we only have to remove the trailing empty limbs. */ if (i > 0) { - MPN_COPY_INCR (scale, scale + i, scalesize - i); - scalesize -= i; - MPN_COPY_INCR (frac, frac + i, fracsize - i); - fracsize -= i; + MPN_COPY_INCR (p.scale, p.scale + i, p.scalesize - i); + p.scalesize -= i; + MPN_COPY_INCR (p.frac, p.frac + i, p.fracsize - i); + p.fracsize -= i; } } else { - if (scale[i] != 0) + if (p.scale[i] != 0) { - count_trailing_zeros (cnt_l, scale[i]); - if (frac[i] != 0) + count_trailing_zeros (cnt_l, p.scale[i]); + if (p.frac[i] != 0) { int cnt_l2; - count_trailing_zeros (cnt_l2, frac[i]); + count_trailing_zeros (cnt_l2, p.frac[i]); if (cnt_l2 < cnt_l) cnt_l = cnt_l2; } } else - count_trailing_zeros (cnt_l, frac[i]); + count_trailing_zeros (cnt_l, p.frac[i]); /* Now shift the numbers to their optimal position. */ if (i == 0 && BITS_PER_MP_LIMB - cnt_h > cnt_l) @@ -583,10 +585,10 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* We cannot save any memory. So just roll both numbers so that the scaling factor has its highest bit set. */ - (void) mpn_lshift (scale, scale, scalesize, cnt_h); - cy = mpn_lshift (frac, frac, fracsize, cnt_h); + (void) mpn_lshift (p.scale, p.scale, p.scalesize, cnt_h); + cy = mpn_lshift (p.frac, p.frac, p.fracsize, cnt_h); if (cy != 0) - frac[fracsize++] = cy; + p.frac[p.fracsize++] = cy; } else if (BITS_PER_MP_LIMB - cnt_h <= cnt_l) { @@ -594,31 +596,31 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, and by packing the non-zero limbs which gain another free one. */ - (void) mpn_rshift (scale, scale + i, scalesize - i, + (void) mpn_rshift (p.scale, p.scale + i, p.scalesize - i, BITS_PER_MP_LIMB - cnt_h); - scalesize -= i + 1; - (void) mpn_rshift (frac, frac + i, fracsize - i, + p.scalesize -= i + 1; + (void) mpn_rshift (p.frac, p.frac + i, p.fracsize - i, BITS_PER_MP_LIMB - cnt_h); - fracsize -= frac[fracsize - i - 1] == 0 ? i + 1 : i; + p.fracsize -= p.frac[p.fracsize - i - 1] == 0 ? i + 1 : i; } else { /* We can only save the memory of the limbs which are zero. The non-zero parts occupy the same number of limbs. */ - (void) mpn_rshift (scale, scale + (i - 1), - scalesize - (i - 1), + (void) mpn_rshift (p.scale, p.scale + (i - 1), + p.scalesize - (i - 1), BITS_PER_MP_LIMB - cnt_h); - scalesize -= i; - (void) mpn_rshift (frac, frac + (i - 1), - fracsize - (i - 1), + p.scalesize -= i; + (void) mpn_rshift (p.frac, p.frac + (i - 1), + p.fracsize - (i - 1), BITS_PER_MP_LIMB - cnt_h); - fracsize -= frac[fracsize - (i - 1) - 1] == 0 ? i : i - 1; + p.fracsize -= p.frac[p.fracsize - (i - 1) - 1] == 0 ? i : i - 1; } } } } - else if (exponent < 0) + else if (p.exponent < 0) { /* |FP| < 1.0. */ int exp10 = 0; @@ -626,40 +628,40 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; /* Now shift the input value to its right place. */ - cy = mpn_lshift (frac, fp_input, fracsize, to_shift); - frac[fracsize++] = cy; - assert (cy == 1 || (frac[fracsize - 2] == 0 && frac[0] == 0)); + cy = mpn_lshift (p.frac, fp_input, p.fracsize, to_shift); + p.frac[p.fracsize++] = cy; + assert (cy == 1 || (p.frac[p.fracsize - 2] == 0 && p.frac[0] == 0)); - expsign = 1; - exponent = -exponent; + p.expsign = 1; + p.exponent = -p.exponent; assert (powers != &_fpioconst_pow10[0]); do { --powers; - if (exponent >= powers->m_expo) + if (p.exponent >= powers->m_expo) { int i, incr, cnt_h, cnt_l; mp_limb_t topval[2]; /* The mpn_mul function expects the first argument to be bigger than the second. */ - if (fracsize < powers->arraysize - _FPIO_CONST_OFFSET) - cy = mpn_mul (tmp, &__tens[powers->arrayoff + if (p.fracsize < powers->arraysize - _FPIO_CONST_OFFSET) + cy = mpn_mul (p.tmp, &__tens[powers->arrayoff + _FPIO_CONST_OFFSET], powers->arraysize - _FPIO_CONST_OFFSET, - frac, fracsize); + p.frac, p.fracsize); else - cy = mpn_mul (tmp, frac, fracsize, + cy = mpn_mul (p.tmp, p.frac, p.fracsize, &__tens[powers->arrayoff + _FPIO_CONST_OFFSET], powers->arraysize - _FPIO_CONST_OFFSET); - tmpsize = fracsize + powers->arraysize - _FPIO_CONST_OFFSET; + p.tmpsize = p.fracsize + powers->arraysize - _FPIO_CONST_OFFSET; if (cy == 0) - --tmpsize; + --p.tmpsize; - count_leading_zeros (cnt_h, tmp[tmpsize - 1]); - incr = (tmpsize - fracsize) * BITS_PER_MP_LIMB + count_leading_zeros (cnt_h, p.tmp[p.tmpsize - 1]); + incr = (p.tmpsize - p.fracsize) * BITS_PER_MP_LIMB + BITS_PER_MP_LIMB - 1 - cnt_h; assert (incr <= powers->p_expo); @@ -667,7 +669,7 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* If we increased the exponent by exactly 3 we have to test for overflow. This is done by comparing with 10 shifted to the right position. */ - if (incr == exponent + 3) + if (incr == p.exponent + 3) { if (cnt_h <= BITS_PER_MP_LIMB - 4) { @@ -689,32 +691,32 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, against 10.0. If it is greater or equal to 10.0 the multiplication was not valid. This is because we cannot determine the number of bits in the result in advance. */ - if (incr < exponent + 3 - || (incr == exponent + 3 && - (tmp[tmpsize - 1] < topval[1] - || (tmp[tmpsize - 1] == topval[1] - && tmp[tmpsize - 2] < topval[0])))) + if (incr < p.exponent + 3 + || (incr == p.exponent + 3 && + (p.tmp[p.tmpsize - 1] < topval[1] + || (p.tmp[p.tmpsize - 1] == topval[1] + && p.tmp[p.tmpsize - 2] < topval[0])))) { /* The factor is right. Adapt binary and decimal exponents. */ - exponent -= incr; + p.exponent -= incr; exp10 |= 1 << explog; /* If this factor yields a number greater or equal to 1.0, we must not shift the non-fractional digits down. */ - if (exponent < 0) - cnt_h += -exponent; + if (p.exponent < 0) + cnt_h += -p.exponent; /* Now we optimize the number representation. */ - for (i = 0; tmp[i] == 0; ++i); + for (i = 0; p.tmp[i] == 0; ++i); if (cnt_h == BITS_PER_MP_LIMB - 1) { - MPN_COPY (frac, tmp + i, tmpsize - i); - fracsize = tmpsize - i; + MPN_COPY (p.frac, p.tmp + i, p.tmpsize - i); + p.fracsize = p.tmpsize - i; } else { - count_trailing_zeros (cnt_l, tmp[i]); + count_trailing_zeros (cnt_l, p.tmp[i]); /* Now shift the numbers to their optimal position. */ if (i == 0 && BITS_PER_MP_LIMB - 1 - cnt_h > cnt_l) @@ -723,15 +725,15 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, number so that the leading digit is in a separate limb. */ - cy = mpn_lshift (frac, tmp, tmpsize, cnt_h + 1); - fracsize = tmpsize + 1; - frac[fracsize - 1] = cy; + cy = mpn_lshift (p.frac, p.tmp, p.tmpsize, cnt_h + 1); + p.fracsize = p.tmpsize + 1; + p.frac[p.fracsize - 1] = cy; } else if (BITS_PER_MP_LIMB - 1 - cnt_h <= cnt_l) { - (void) mpn_rshift (frac, tmp + i, tmpsize - i, + (void) mpn_rshift (p.frac, p.tmp + i, p.tmpsize - i, BITS_PER_MP_LIMB - 1 - cnt_h); - fracsize = tmpsize - i; + p.fracsize = p.tmpsize - i; } else { @@ -739,41 +741,41 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, are zero. The non-zero parts occupy the same number of limbs. */ - (void) mpn_rshift (frac, tmp + (i - 1), - tmpsize - (i - 1), + (void) mpn_rshift (p.frac, p.tmp + (i - 1), + p.tmpsize - (i - 1), BITS_PER_MP_LIMB - 1 - cnt_h); - fracsize = tmpsize - (i - 1); + p.fracsize = p.tmpsize - (i - 1); } } } } --explog; } - while (powers != &_fpioconst_pow10[1] && exponent > 0); + while (powers != &_fpioconst_pow10[1] && p.exponent > 0); /* All factors but 10^-1 are tested now. */ - if (exponent > 0) + if (p.exponent > 0) { int cnt_l; - cy = mpn_mul_1 (tmp, frac, fracsize, 10); - tmpsize = fracsize; - assert (cy == 0 || tmp[tmpsize - 1] < 20); + cy = mpn_mul_1 (p.tmp, p.frac, p.fracsize, 10); + p.tmpsize = p.fracsize; + assert (cy == 0 || p.tmp[p.tmpsize - 1] < 20); - count_trailing_zeros (cnt_l, tmp[0]); - if (cnt_l < MIN (4, exponent)) + count_trailing_zeros (cnt_l, p.tmp[0]); + if (cnt_l < MIN (4, p.exponent)) { - cy = mpn_lshift (frac, tmp, tmpsize, - BITS_PER_MP_LIMB - MIN (4, exponent)); + cy = mpn_lshift (p.frac, p.tmp, p.tmpsize, + BITS_PER_MP_LIMB - MIN (4, p.exponent)); if (cy != 0) - frac[tmpsize++] = cy; + p.frac[p.tmpsize++] = cy; } else - (void) mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent)); - fracsize = tmpsize; + (void) mpn_rshift (p.frac, p.tmp, p.tmpsize, MIN (4, p.exponent)); + p.fracsize = p.tmpsize; exp10 |= 1; - assert (frac[fracsize - 1] < 10); + assert (p.frac[p.fracsize - 1] < 10); } - exponent = exp10; + p.exponent = exp10; } else { @@ -781,13 +783,13 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, numbers are in the range of 1.0 <= |fp| < 8.0. We simply shift it to the right place and divide it by 1.0 to get the leading digit. (Of course this division is not really made.) */ - assert (0 <= exponent && exponent < 3 && - exponent + to_shift < BITS_PER_MP_LIMB); + assert (0 <= p.exponent && p.exponent < 3 && + p.exponent + to_shift < BITS_PER_MP_LIMB); /* Now shift the input value to its right place. */ - cy = mpn_lshift (frac, fp_input, fracsize, (exponent + to_shift)); - frac[fracsize++] = cy; - exponent = 0; + cy = mpn_lshift (p.frac, fp_input, p.fracsize, (p.exponent + to_shift)); + p.frac[p.fracsize++] = cy; + p.exponent = 0; } { @@ -805,7 +807,7 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, if (spec == 'e') { - type = info->spec; + p.type = info->spec; intdig_max = 1; fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4; @@ -815,15 +817,15 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, } else if (spec == 'f') { - type = 'f'; + p.type = 'f'; fracdig_min = fracdig_max = info->prec < 0 ? 6 : info->prec; dig_max = __INT_MAX__; /* Unlimited. */ significant = 1; /* Does not matter here. */ - if (expsign == 0) + if (p.expsign == 0) { - intdig_max = exponent + 1; + intdig_max = p.exponent + 1; /* This can be really big! */ /* XXX Maybe malloc if too big? */ - chars_needed = (size_t) exponent + 1 + 1 + (size_t) fracdig_max; + chars_needed = (size_t) p.exponent + 1 + 1 + (size_t) fracdig_max; } else { @@ -834,21 +836,21 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, else { dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec); - if ((expsign == 0 && exponent >= dig_max) - || (expsign != 0 && exponent > 4)) + if ((p.expsign == 0 && p.exponent >= dig_max) + || (p.expsign != 0 && p.exponent > 4)) { if ('g' - 'G' == 'e' - 'E') - type = 'E' + (info->spec - 'G'); + p.type = 'E' + (info->spec - 'G'); else - type = isupper (info->spec) ? 'E' : 'e'; + p.type = isupper (info->spec) ? 'E' : 'e'; fracdig_max = dig_max - 1; intdig_max = 1; chars_needed = 1 + 1 + (size_t) fracdig_max + 1 + 1 + 4; } else { - type = 'f'; - intdig_max = expsign == 0 ? exponent + 1 : 0; + p.type = 'f'; + intdig_max = p.expsign == 0 ? p.exponent + 1 : 0; fracdig_max = dig_max - intdig_max; /* We need space for the significant digits and perhaps for leading zeros when < 1.0. The number of leading @@ -898,18 +900,18 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, wcp = wstartp = wbuffer + 2; /* Let room for rounding. */ /* Do the real work: put digits in allocated buffer. */ - if (expsign == 0 || type != 'f') + if (p.expsign == 0 || p.type != 'f') { - assert (expsign == 0 || intdig_max == 1); + assert (p.expsign == 0 || intdig_max == 1); while (intdig_no < intdig_max) { ++intdig_no; - *wcp++ = hack_digit (); + *wcp++ = hack_digit (&p); } significant = 1; if (info->alt || fracdig_min > 0 - || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0))) + || (fracdig_max > 0 && (p.fracsize > 1 || p.frac[0] != 0))) *wcp++ = decimalwc; } else @@ -917,7 +919,7 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* |fp| < 1.0 and the selected type is 'f', so put "0." in the buffer. */ *wcp++ = L_('0'); - --exponent; + --p.exponent; *wcp++ = decimalwc; } @@ -925,10 +927,10 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, int fracdig_no = 0; int added_zeros = 0; while (fracdig_no < fracdig_min + added_zeros - || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0))) + || (fracdig_no < fracdig_max && (p.fracsize > 1 || p.frac[0] != 0))) { ++fracdig_no; - *wcp = hack_digit (); + *wcp = hack_digit (&p); if (*wcp++ != L_('0')) significant = 1; else if (significant == 0) @@ -941,19 +943,19 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, /* Do rounding. */ last_digit = wcp[-1] != decimalwc ? wcp[-1] : wcp[-2]; - next_digit =hack_digit (); + next_digit =hack_digit (&p); if (next_digit != L_('0') && next_digit != L_('5')) more_bits = true; - else if (fracsize == 1 && frac[0] == 0) + else if (p.fracsize == 1 && p.frac[0] == 0) /* Rest of the number is zero. */ more_bits = false; - else if (scalesize == 0) + else if (p.scalesize == 0) { /* Here we have to see whether all limbs are zero since no normalization happened. */ - size_t lcnt = fracsize; - while (lcnt >= 1 && frac[lcnt - 1] == 0) + size_t lcnt = p.fracsize; + while (lcnt >= 1 && p.frac[lcnt - 1] == 0) --lcnt; more_bits = lcnt > 0; } @@ -982,7 +984,7 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, if (*wtp != decimalwc) /* Round up. */ (*wtp)++; - else if (__builtin_expect (spec == 'g' && type == 'f' && info->alt + else if (__builtin_expect (spec == 'g' && p.type == 'f' && info->alt && wtp == wstartp + 1 && wstartp[0] == L_('0'), 0)) @@ -1007,16 +1009,16 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, else /* It is more critical. All digits were 9's. */ { - if (type != 'f') + if (p.type != 'f') { *wstartp = '1'; - exponent += expsign == 0 ? 1 : -1; + p.exponent += p.expsign == 0 ? 1 : -1; /* The above exponent adjustment could lead to 1.0e-00, e.g. for 0.999999999. Make sure exponent 0 always uses + sign. */ - if (exponent == 0) - expsign = 0; + if (p.exponent == 0) + p.expsign = 0; } else if (intdig_no == dig_max) { @@ -1036,9 +1038,9 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, fracdig_no += intdig_no; intdig_no = 1; fracdig_max = intdig_max - intdig_no; - ++exponent; + ++p.exponent; /* Now we must print the exponent. */ - type = isupper (info->spec) ? 'E' : 'e'; + p.type = isupper (info->spec) ? 'E' : 'e'; } else { @@ -1085,9 +1087,9 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, } /* Write the exponent if it is needed. */ - if (type != 'f') + if (p.type != 'f') { - if (__builtin_expect (expsign != 0 && exponent == 4 && spec == 'g', 0)) + if (__builtin_expect (p.expsign != 0 && p.exponent == 4 && spec == 'g', 0)) { /* This is another special case. The exponent of the number is really smaller than -4, which requires the 'e'/'E' format. @@ -1108,26 +1110,26 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp, } else { - *wcp++ = (wchar_t) type; - *wcp++ = expsign ? L_('-') : L_('+'); + *wcp++ = (wchar_t) p.type; + *wcp++ = p.expsign ? L_('-') : L_('+'); /* Find the magnitude of the exponent. */ expscale = 10; - while (expscale <= exponent) + while (expscale <= p.exponent) expscale *= 10; - if (exponent < 10) + if (p.exponent < 10) /* Exponent always has at least two digits. */ *wcp++ = L_('0'); else do { expscale /= 10; - *wcp++ = L_('0') + (exponent / expscale); - exponent %= expscale; + *wcp++ = L_('0') + (p.exponent / expscale); + p.exponent %= expscale; } while (expscale > 10); - *wcp++ = L_('0') + exponent; + *wcp++ = L_('0') + p.exponent; } } diff --git a/libtool.m4 b/libtool.m4 index 24d13f34409..9927c3684e3 100644 --- a/libtool.m4 +++ b/libtool.m4 @@ -3653,7 +3653,7 @@ m4_if([$1], [CXX], [ *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' @@ -3803,7 +3803,7 @@ m4_if([$1], [CXX], [ *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; osf3* | osf4* | osf5*) case $cc_basename in @@ -3970,7 +3970,7 @@ m4_if([$1], [CXX], [ *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; sysv4*MP*) @@ -4098,7 +4098,7 @@ m4_if([$1], [CXX], [ *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; osf3* | osf4* | osf5*)