diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-06-13 14:26:53 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-06-13 14:26:53 +0000 |
commit | fad96109a42625b9c6881e4c1b703b4aee7f64ce (patch) | |
tree | 98094fe155b81e6d4c38e19597491ceb91755cdd | |
parent | 875d2ea2b87818e1e88b0135796f788e492969d2 (diff) | |
parent | 09a871c46619af0461d2c079d4de953745a11b68 (diff) | |
download | gcc-fad96109a42625b9c6881e4c1b703b4aee7f64ce.zip gcc-fad96109a42625b9c6881e4c1b703b4aee7f64ce.tar.gz gcc-fad96109a42625b9c6881e4c1b703b4aee7f64ce.tar.bz2 |
Merge from trunk revision 249156.
From-SVN: r249160
73 files changed, 2690 insertions, 576 deletions
@@ -1,3 +1,7 @@ +2017-06-12 Segher Boessenkool <segher@kernel.crashing.org> + + * config.gcc: Remove rs6000/e500.h from tm_file for all targets. + 2017-06-03 Eric Botcazou <ebotcazou@adacore.com> * configure.ac (*-*-linux-android*): Set target_makefile_frag. diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog index 4f729db..ffd1718 100644 --- a/fixincludes/ChangeLog +++ b/fixincludes/ChangeLog @@ -1,3 +1,8 @@ +2017-06-12 Doug Rupp <rupp@adacore.com> + + * inclhack.def (AAB_vxworks_stdint): Remove hack. + * fixincl.x: Regenerate. + 2017-02-25 John David Anglin <danglin@gcc.gnu.org> PR target/68739 diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x index c5be74f..8d8be9c 100644 --- a/fixincludes/fixincl.x +++ b/fixincludes/fixincl.x @@ -1,12 +1,12 @@ /* -*- buffer-read-only: t -*- vi: set ro: - * + * * DO NOT EDIT THIS FILE (fixincl.x) - * - * It has been AutoGen-ed Saturday February 25, 2017 at 03:25:44 PM EST + * + * It has been AutoGen-ed June 8, 2017 at 10:50:04 AM by AutoGen 5.18.4 * From the definitions inclhack.def * and the template file fixincl */ -/* DO NOT SVN-MERGE THIS FILE, EITHER Sat 25 Feb 2017 15:25:44 EST +/* DO NOT SVN-MERGE THIS FILE, EITHER Thu Jun 8 10:50:04 CEST 2017 * * You must regenerate it. Use the ./genfixes script. * @@ -15,7 +15,7 @@ * certain ANSI-incompatible system header files which are fixed to work * correctly with ANSI C and placed in a directory that GNU C will search. * - * This file contains 248 fixup descriptions. + * This file contains 247 fixup descriptions. * * See README for more information. * @@ -581,120 +581,6 @@ static const char* apzAab_Vxworks_Regs_VxtypesPatch[] = { /* * * * * * * * * * * * * * * * * * * * * * * * * * * - * Description of Aab_Vxworks_Stdint fix - */ -tSCC zAab_Vxworks_StdintName[] = - "AAB_vxworks_stdint"; - -/* - * File name selection pattern - */ -tSCC zAab_Vxworks_StdintList[] = - "stdint.h\0"; -/* - * Machine/OS name selection pattern - */ -tSCC* apzAab_Vxworks_StdintMachs[] = { - "*-*-vxworks*", - (const char*)NULL }; -#define AAB_VXWORKS_STDINT_TEST_CT 0 -#define aAab_Vxworks_StdintTests (tTestDesc*)NULL - -/* - * Fix Command Arguments for Aab_Vxworks_Stdint - */ -static const char* apzAab_Vxworks_StdintPatch[] = { -"#ifndef _STDINT_H\n\ -#define _STDINT_H\n\ -/* get int*_t, uint*_t */\n\ -#include <types/vxTypes.h>\n\n\ -/* get legacy vxworks types for compatibility */\n\ -#include <types/vxTypesOld.h>\n\n\ -typedef long intptr_t;\n\ -typedef unsigned long uintptr_t;\n\n\ -typedef int64_t intmax_t;\n\ -typedef uint64_t uintmax_t;\n\n\ -typedef int8_t int_least8_t;\n\ -typedef int16_t int_least16_t;\n\ -typedef int32_t int_least32_t;\n\ -typedef int64_t int_least64_t;\n\n\ -typedef uint8_t uint_least8_t;\n\ -typedef uint16_t uint_least16_t;\n\ -typedef uint32_t uint_least32_t;\n\ -typedef uint64_t uint_least64_t;\n\n\ -typedef int8_t int_fast8_t;\n\ -typedef int int_fast16_t;\n\ -typedef int32_t int_fast32_t;\n\ -typedef int64_t int_fast64_t;\n\n\ -typedef uint8_t uint_fast8_t;\n\ -typedef unsigned int uint_fast16_t;\n\ -typedef uint32_t uint_fast32_t;\n\ -typedef uint64_t uint_fast64_t;\n\n\ -/* Ranges */\n\ -#define UINT8_MAX (~(uint8_t)0)\n\ -#define UINT8_MIN 0\n\ -#define UINT16_MAX (~(uint16_t)0)\n\ -#define UINT16_MIN 0\n\ -#define UINT32_MAX (~(uint32_t)0)\n\ -#define UINT32_MIN 0\n\ -#define UINT64_MAX (~(uint64_t)0)\n\ -#define UINT64_MIN 0\n\n\ -#define UINTPTR_MAX (~(uintptr_t)0)\n\ -#define UINTPTR_MIN 0\n\n\ -/* Need to do int_fast16_t as well, as type\n\ - size may be architecture dependent */\n\ -#define UINT_FAST16_MAX (~(uint_fast16_t)0)\n\ -#define UINT_FAST16_MAX 0\n\n\ -#define INT8_MAX (UINT8_MAX>>1)\n\ -#define INT8_MIN (INT8_MAX+1)\n\ -#define INT16_MAX (UINT16_MAX>>1)\n\ -#define INT16_MIN (INT16_MAX+1)\n\ -#define INT32_MAX (UINT32_MAX>>1)\n\ -#define INT32_MIN (INT32_MAX+1)\n\ -#define INT64_MAX (UINT64_MAX>>1)\n\ -#define INT64_MIN (INT64_MAX+1)\n\n\ -#define INTPTR_MAX (UINTPTR_MAX>>1)\n\ -#define INTPTR_MIN (INTPTR_MAX+1)\t\n\n\ -#define INT_FAST16_MAX (UINT_FAST16_MAX>>1)\n\ -#define INT_FAST16_MIN (INT_FAST16_MAX+1)\n\n\ -/* now define equiv. constants */\n\ -#define UINT_FAST8_MAX UINT8_MAX\n\ -#define UINT_FAST8_MIN UINT_FAST8_MIN\n\ -#define INT_FAST8_MAX INT8_MAX\n\ -#define INT_FAST8_MIN INT8_MIN\n\ -#define UINT_FAST32_MAX UINT32_MAX\n\ -#define UINT_FAST32_MIN UINT32_MIN\n\ -#define INT_FAST32_MAX INT32_MAX\n\ -#define INT_FAST32_MIN INT32_MIN\n\ -#define UINT_FAST64_MAX UINT64_MAX\n\ -#define UINT_FAST64_MIN UINT64_MIN\n\ -#define INT_FAST64_MAX INT64_MAX\n\ -#define INT_FAST64_MIN INT64_MIN\n\n\ -#define UINT_LEAST8_MAX UINT8_MAX\n\ -#define UINT_LEAST8_MIN UINT8_MIN\n\ -#define INT_LEAST8_MAX INT8_MAX\n\ -#define INT_LEAST8_MIN INT8_MIN\n\ -#define UINT_LEAST16_MAX UINT16_MAX\n\ -#define UINT_LEAST16_MIN UINT16_MIN\n\ -#define INT_LEAST16_MAX INT16_MAX\n\ -#define INT_LEAST16_MIN INT16_MIN\n\ -#define UINT_LEAST32_MAX UINT32_MAX\n\ -#define UINT_LEAST32_MIN UINT32_MIN\n\ -#define INT_LEAST32_MAX INT32_MAX\n\ -#define INT_LEAST32_MIN INT32_MIN\n\ -#define UINT_LEAST64_MAX UINT64_MAX\n\ -#define UINT_LEAST64_MIN UINT64_MIN\n\ -#define INT_LEAST64_MAX INT64_MAX\n\ -#define INT_LEAST64_MIN INT64_MIN\n\n\ -#define UINTMAX_MAX UINT64_MAX\n\ -#define UINTMAX_MIN UINT64_MIN\n\ -#define INTMAX_MAX INT64_MAX\n\ -#define INTMAX_MIN INT64_MIN\n\n\ -#endif", - (char*)NULL }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * - * * Description of Aab_Vxworks_Unistd fix */ tSCC zAab_Vxworks_UnistdName[] = @@ -10141,7 +10027,7 @@ static const char* apzX11_SprintfPatch[] = { */ #define REGEX_COUNT 285 #define MACH_LIST_SIZE_LIMIT 187 -#define FIX_COUNT 248 +#define FIX_COUNT 247 /* * Enumerate the fixes @@ -10157,7 +10043,6 @@ typedef enum { AAB_SUN_MEMCPY_FIXIDX, AAB_VXWORKS_ASSERT_FIXIDX, AAB_VXWORKS_REGS_VXTYPES_FIXIDX, - AAB_VXWORKS_STDINT_FIXIDX, AAB_VXWORKS_UNISTD_FIXIDX, AIX_ASSERT_FIXIDX, AIX_COMPLEX_FIXIDX, @@ -10448,11 +10333,6 @@ tFixDesc fixDescList[ FIX_COUNT ] = { AAB_VXWORKS_REGS_VXTYPES_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT, aAab_Vxworks_Regs_VxtypesTests, apzAab_Vxworks_Regs_VxtypesPatch, 0 }, - { zAab_Vxworks_StdintName, zAab_Vxworks_StdintList, - apzAab_Vxworks_StdintMachs, - AAB_VXWORKS_STDINT_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT, - aAab_Vxworks_StdintTests, apzAab_Vxworks_StdintPatch, 0 }, - { zAab_Vxworks_UnistdName, zAab_Vxworks_UnistdList, apzAab_Vxworks_UnistdMachs, AAB_VXWORKS_UNISTD_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT, diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def index 8a5514f..fd0034f 100644 --- a/fixincludes/inclhack.def +++ b/fixincludes/inclhack.def @@ -427,122 +427,6 @@ fix = { }; /* - * Make VxWorks stdint.h a bit more compliant - add typedefs - */ -fix = { - hackname = AAB_vxworks_stdint; - files = stdint.h; - mach = "*-*-vxworks*"; - - replace = <<- _EndOfHeader_ - #ifndef _STDINT_H - #define _STDINT_H - /* get int*_t, uint*_t */ - #include <types/vxTypes.h> - - /* get legacy vxworks types for compatibility */ - #include <types/vxTypesOld.h> - - typedef long intptr_t; - typedef unsigned long uintptr_t; - - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; - - typedef int8_t int_least8_t; - typedef int16_t int_least16_t; - typedef int32_t int_least32_t; - typedef int64_t int_least64_t; - - typedef uint8_t uint_least8_t; - typedef uint16_t uint_least16_t; - typedef uint32_t uint_least32_t; - typedef uint64_t uint_least64_t; - - typedef int8_t int_fast8_t; - typedef int int_fast16_t; - typedef int32_t int_fast32_t; - typedef int64_t int_fast64_t; - - typedef uint8_t uint_fast8_t; - typedef unsigned int uint_fast16_t; - typedef uint32_t uint_fast32_t; - typedef uint64_t uint_fast64_t; - - /* Ranges */ - #define UINT8_MAX (~(uint8_t)0) - #define UINT8_MIN 0 - #define UINT16_MAX (~(uint16_t)0) - #define UINT16_MIN 0 - #define UINT32_MAX (~(uint32_t)0) - #define UINT32_MIN 0 - #define UINT64_MAX (~(uint64_t)0) - #define UINT64_MIN 0 - - #define UINTPTR_MAX (~(uintptr_t)0) - #define UINTPTR_MIN 0 - - /* Need to do int_fast16_t as well, as type - size may be architecture dependent */ - #define UINT_FAST16_MAX (~(uint_fast16_t)0) - #define UINT_FAST16_MAX 0 - - #define INT8_MAX (UINT8_MAX>>1) - #define INT8_MIN (INT8_MAX+1) - #define INT16_MAX (UINT16_MAX>>1) - #define INT16_MIN (INT16_MAX+1) - #define INT32_MAX (UINT32_MAX>>1) - #define INT32_MIN (INT32_MAX+1) - #define INT64_MAX (UINT64_MAX>>1) - #define INT64_MIN (INT64_MAX+1) - - #define INTPTR_MAX (UINTPTR_MAX>>1) - #define INTPTR_MIN (INTPTR_MAX+1) - - #define INT_FAST16_MAX (UINT_FAST16_MAX>>1) - #define INT_FAST16_MIN (INT_FAST16_MAX+1) - - /* now define equiv. constants */ - #define UINT_FAST8_MAX UINT8_MAX - #define UINT_FAST8_MIN UINT_FAST8_MIN - #define INT_FAST8_MAX INT8_MAX - #define INT_FAST8_MIN INT8_MIN - #define UINT_FAST32_MAX UINT32_MAX - #define UINT_FAST32_MIN UINT32_MIN - #define INT_FAST32_MAX INT32_MAX - #define INT_FAST32_MIN INT32_MIN - #define UINT_FAST64_MAX UINT64_MAX - #define UINT_FAST64_MIN UINT64_MIN - #define INT_FAST64_MAX INT64_MAX - #define INT_FAST64_MIN INT64_MIN - - #define UINT_LEAST8_MAX UINT8_MAX - #define UINT_LEAST8_MIN UINT8_MIN - #define INT_LEAST8_MAX INT8_MAX - #define INT_LEAST8_MIN INT8_MIN - #define UINT_LEAST16_MAX UINT16_MAX - #define UINT_LEAST16_MIN UINT16_MIN - #define INT_LEAST16_MAX INT16_MAX - #define INT_LEAST16_MIN INT16_MIN - #define UINT_LEAST32_MAX UINT32_MAX - #define UINT_LEAST32_MIN UINT32_MIN - #define INT_LEAST32_MAX INT32_MAX - #define INT_LEAST32_MIN INT32_MIN - #define UINT_LEAST64_MAX UINT64_MAX - #define UINT_LEAST64_MIN UINT64_MIN - #define INT_LEAST64_MAX INT64_MAX - #define INT_LEAST64_MIN INT64_MIN - - #define UINTMAX_MAX UINT64_MAX - #define UINTMAX_MIN UINT64_MIN - #define INTMAX_MAX INT64_MAX - #define INTMAX_MIN INT64_MIN - - #endif - _EndOfHeader_; -}; - -/* * This hack makes makes unistd.h more POSIX-compliant on VxWorks */ fix = { diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 192e869..e0a894f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,167 @@ +2017-06-13 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/80803 + PR tree-optimization/81063 + * tree-sra.c (subtree_mark_written_and_enqueue): Move up in the file. + (propagate_subaccesses_across_link): Enqueue subtree whenever + necessary instead of relying on the caller. + +2017-06-13 Martin Jambor <mjambor@suse.cz> + + * tree-sra.c (add_access_to_work_queue): Only enqueue accesses + that have a first_link. + (sort_and_splice_var_accesses): Do not check first_link before + enquing. + (subtree_mark_written_and_enqueue): Likewise. + (propagate_all_subaccesses): Likewise and do not stop at first + parent with a first_link. + +2017-06-13 Martin Jambor <mjambor@suse.cz> + + * tree-sra.c (dump_access_tree_1): Fix accidental dumping to stderr + instead of f. + +2017-06-13 Yury Gribov <tetra2005@gmail.com> + + * match.pd: New pattern. + +2017-06-13 Yury Gribov <tetra2005@gmail.com> + + * tree-vrp.c (is_masked_range_test): New function. + (register_edge_assert_for): Determine ranges for + some bit tests. + +2017-06-13 Yury Gribov <tetra2005@gmail.com> + + PR tree-optimization/67328 + * fold-const.c (maskable_range_p): New function. + (build_range_check): Generate bittests if possible. + +2017-06-13 Martin Liska <mliska@suse.cz> + + * gimple-pretty-print.c (dump_probability): Add new argument. + (dump_edge_probability): Dump both probability and count. + (dump_gimple_label): Likewise. + (dump_gimple_bb_header): Likewise. + +2017-06-13 Georg-Johann Lay <avr@gjlay.de> + + PR target/81072 + * config/avr/avr-devices.c: Fix indentation. + * config/avr/gen-avr-mmcu-specs.c: Dito. + +2017-06-13 Richard Biener <rguenther@suse.de> + + * tree-vect-loop.c (vect_model_reduction_cost): Do not fail, + instead get vector type from stmt_info. + (vectorizable_reduction): Adjust. Remove dead code. + +2017-06-13 Richard Biener <rguenther@suse.de> + + PR middle-end/81065 + * fold-const.c (extract_muldiv_1): Remove bogus distribution + case of C * (x * C2 + C3). + (fold_addr_of_array_ref_difference): Properly fold index difference. + +2017-06-12 David S. Miller <davem@davemloft.net> + + PR target/80968 + * config/sparc/sparc.md (return expander): Emit frame blockage if + function uses alloca. + +2017-06-12 Richard Sandiford <richard.sandiford@linaro.org> + + * combine.c (make_field_assignment): Check len rather than the mode + precision when calling force_to_mode. + +2017-06-12 Georg-Johann Lay <avr@gjlay.de> + + Support multilibs and devices that see flash in RAM address range. + + PR target/81072 + * config/avr/avr-arch.h (avr_arch_id) <ARCH_AVRXMEGA3>: New enum. + (avr_mcu_t) <flash_pm_offset>: New field. + (avr_device_specific_features) <AVR_ISA_RCALL>: New enum. + * config/avr/avr.h (AVR_SHORT_CALLS): New define. + (AVR_HAVE_JMP_CALL): Don't set if AVR_SHORT_CALLS. + (AVR_TINY_PM_OFFSET): Remove macro. + * config/avr/avr.opt (-mshort-calls): New option. + * config/avr/gen-avr-mmcu-specs.c (print_mcu) + [*self_spec]: Add / remove -mshort-calls depending on AVR_ISA_RCALL. + * config/avr/avr-c.c (avr_cpu_cpp_builtins) + <__AVR_SHORT_CALLS__>: Built-in define if AVR_SHORT_CALLS. + <__AVR_HAVE_JMP_CALL__>: Use AVR_HAVE_JMP_CALL as condition + instead of avr_arch->have_jmp_call. + <__AVR_PM_BASE_ADDRESS__>: Built-in define if avr_arch->flash_pm_offset. + [AVR_TINY] <__AVR_TINY_PM_BASE_ADDRESS__>: Use + avr_arch->flash_pm_offset to define. + * config/avr/avr-devices.c (avr_arch_types): Add initializers for + new field flash_pm_offset. Add entry for avrxmega3. + (avr_texinfo): Add entry for avrxmega3. + * config/avr/avr-mcus.def: Add entries for: avrxmega3, + attiny212, attiny214, + attiny412, attiny414, attiny416, attiny417, + attiny814, attiny816, attiny817, + attiny1614, attiny1616, attiny1617, + attiny3214, attiny3216, attiny3217. + * config/avr/avr.c (avr_assemble_integer)[AVR_TINY]: Use + avr_arch->flash_pm_offset instead of AVR_TINY_PM_OFFSET. + (avr_print_operand_address) [AVR_TINY]: Same. + (avr_asm_init_sections) <readonly_data_section>: Only patch + callback if avr_arch->flash_pm_offset = 0. + (avr_asm_named_section) <avr_need_copy_data_p>: Skip setting it + for rodata if avr_arch->flash_pm_offset != 0. + (avr_encode_section_info) [AVR_TINY]: Adjust comment. + * config/avr/genmultilib.awk (dir_rcall, opt_rcall): New vars. + (opts) [AVR_ISA_RCALL]: Append opt_rcall. + (m_options): Append opt_rcall. + (m_dirnames): Append dir_rcall. + * config/avr/t-multilib: Regenerate. + + * configure.ac [target=avr]: Check whether avrxmega3 default + linker description file works as needed. + * configure: Regenerate. + * doc/avr-mmcu.texi: Regenerate. + * doc/invoke.texi (AVR Options) <-mshort-calls>: Document it. + <__AVR_ARCH__>: Document avrxmega3 and 103. + <__AVR_HAVE_JMP_CALL__>: Adjust documentation. + <__AVR_SHORT_CALLS__>: Document it. + <__AVR_PM_BASE_ADDRESS__>: Document it. + * doc/extend.texi (AVR Options) <-mshort-calls>: Document it. + (AVR Variable Attributes) <progmem>: Document this is + not needed for avrxmega3. + (AVR Named Address Spaces) <__flash>: Dito. + +2017-06-12 Jan Hubicka <hubicka@ucw.cz> + + * cgraph.c (cgraph_node::dump): Complain about profile insanities. + +2017-06-12 Doug Rupp <rupp@adacore.com> + + * config.gcc (*-*-vxworks*): Set use_gcc_stdint to "provide". + Append vxworks-stdint.h to the tm_file list. + * config/vxworks-stdint.h: New file. + +2017-06-12 Martin Liska <mliska@suse.cz> + + PR tree-optimization/81041 + * tree-profile.c (gimple_gen_ic_func_profiler): + Create an extra BB in profile-generate + (gimple_gen_time_profiler): Likewise. + +2017-06-12 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/81003 + * tree-ssa-reassoc.c (force_into_ssa_name): New function. + (update_range_test): Use it instead of force_gimple_operand_gsi. + +2017-06-12 Richard Biener <rguenther@suse.de> + + PR tree-optimization/81053 + * tree-vect-loop.c (vect_is_simple_reduction): Handle PHI + with backedge value not defined in loop. Simplify def stmt + compute. + 2017-06-11 Tom de Vries <tom@codesourcery.com> PR target/79939 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index eed0e9e..0cdf576 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20170612 +20170613 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index e7f2b86..30290fa 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2017-06-12 Eric Botcazou <ebotcazou@adacore.com> + + PR bootstrap/80897 + * exp_ch3.adb (Make_Predefined_Primitive_Specs): Use Positive index. + +2017-06-12 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/81070 + * s-interr-hwint.adb: Reinstate. + * gcc-interface/Makefile.in (RTEMS): Use it again. + 2017-06-08 Olivier Hainque <hainque@adacore.com> * vx_crtbegin_auto.c: Update year in copyright notice. diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 6d9bdaa..00d74c5 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -9216,7 +9216,7 @@ package body Exp_Ch3 is declare Stream_Op_TSS_Names : - constant array (Integer range <>) of TSS_Name_Type := + constant array (Positive range <>) of TSS_Name_Type := (TSS_Stream_Read, TSS_Stream_Write, TSS_Stream_Input, diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in index d44d68a..1030a67 100644 --- a/gcc/ada/gcc-interface/Makefile.in +++ b/gcc/ada/gcc-interface/Makefile.in @@ -1747,7 +1747,7 @@ ifeq ($(strip $(filter-out rtems%,$(target_os))),) s-taspri.ads<s-taspri-posix.ads \ s-tpopsp.adb<s-tpopsp-tls.adb \ s-stchop.adb<s-stchop-rtems.adb \ - s-interr.adb<s-interr-vxworks.adb + s-interr.adb<s-interr-hwint.adb endif # PikeOS diff --git a/gcc/ada/s-interr-hwint.adb b/gcc/ada/s-interr-hwint.adb new file mode 100644 index 0000000..8e2950f --- /dev/null +++ b/gcc/ada/s-interr-hwint.adb @@ -0,0 +1,1110 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS -- +-- -- +-- S Y S T E M . I N T E R R U P T S -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 1992-2014, Free Software Foundation, Inc. -- +-- -- +-- GNARL is free software; you can redistribute it and/or modify it under -- +-- terms of the GNU General Public License as published by the Free Soft- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- <http://www.gnu.org/licenses/>. -- +-- -- +-- GNARL was developed by the GNARL team at Florida State University. -- +-- Extensive contributions were provided by Ada Core Technologies, Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- Invariants: + +-- All user-handlable signals are masked at all times in all tasks/threads +-- except possibly for the Interrupt_Manager task. + +-- When a user task wants to have the effect of masking/unmasking an signal, +-- it must call Block_Interrupt/Unblock_Interrupt, which will have the effect +-- of unmasking/masking the signal in the Interrupt_Manager task. These +-- comments do not apply to vectored hardware interrupts, which may be masked +-- or unmasked using routined interfaced to the relevant embedded RTOS system +-- calls. + +-- Once we associate a Signal_Server_Task with an signal, the task never goes +-- away, and we never remove the association. On the other hand, it is more +-- convenient to terminate an associated Interrupt_Server_Task for a vectored +-- hardware interrupt (since we use a binary semaphore for synchronization +-- with the umbrella handler). + +-- There is no more than one signal per Signal_Server_Task and no more than +-- one Signal_Server_Task per signal. The same relation holds for hardware +-- interrupts and Interrupt_Server_Task's at any given time. That is, only +-- one non-terminated Interrupt_Server_Task exists for a give interrupt at +-- any time. + +-- Within this package, the lock L is used to protect the various status +-- tables. If there is a Server_Task associated with a signal or interrupt, +-- we use the per-task lock of the Server_Task instead so that we protect the +-- status between Interrupt_Manager and Server_Task. Protection among service +-- requests are ensured via user calls to the Interrupt_Manager entries. + +-- This is reasonably generic version of this package, supporting vectored +-- hardware interrupts using non-RTOS specific adapter routines which should +-- easily implemented on any RTOS capable of supporting GNAT. + +with Ada.Unchecked_Conversion; +with Ada.Task_Identification; + +with Interfaces.C; use Interfaces.C; +with System.OS_Interface; use System.OS_Interface; +with System.Interrupt_Management; +with System.Task_Primitives.Operations; +with System.Storage_Elements; +with System.Tasking.Utilities; + +with System.Tasking.Rendezvous; +pragma Elaborate_All (System.Tasking.Rendezvous); + +package body System.Interrupts is + + use Tasking; + + package POP renames System.Task_Primitives.Operations; + + function To_Ada is new Ada.Unchecked_Conversion + (System.Tasking.Task_Id, Ada.Task_Identification.Task_Id); + + function To_System is new Ada.Unchecked_Conversion + (Ada.Task_Identification.Task_Id, Task_Id); + + ----------------- + -- Local Tasks -- + ----------------- + + -- WARNING: System.Tasking.Stages performs calls to this task with low- + -- level constructs. Do not change this spec without synchronizing it. + + task Interrupt_Manager is + entry Detach_Interrupt_Entries (T : Task_Id); + + entry Attach_Handler + (New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean; + Restoration : Boolean := False); + + entry Exchange_Handler + (Old_Handler : out Parameterless_Handler; + New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean); + + entry Detach_Handler + (Interrupt : Interrupt_ID; + Static : Boolean); + + entry Bind_Interrupt_To_Entry + (T : Task_Id; + E : Task_Entry_Index; + Interrupt : Interrupt_ID); + + pragma Interrupt_Priority (System.Interrupt_Priority'First); + end Interrupt_Manager; + + task type Interrupt_Server_Task + (Interrupt : Interrupt_ID; + Int_Sema : Binary_Semaphore_Id) + is + -- Server task for vectored hardware interrupt handling + + pragma Interrupt_Priority (System.Interrupt_Priority'First + 2); + end Interrupt_Server_Task; + + type Interrupt_Task_Access is access Interrupt_Server_Task; + + ------------------------------- + -- Local Types and Variables -- + ------------------------------- + + type Entry_Assoc is record + T : Task_Id; + E : Task_Entry_Index; + end record; + + type Handler_Assoc is record + H : Parameterless_Handler; + Static : Boolean; -- Indicates static binding; + end record; + + User_Handler : array (Interrupt_ID) of Handler_Assoc := + (others => (null, Static => False)); + pragma Volatile_Components (User_Handler); + -- Holds the protected procedure handler (if any) and its Static + -- information for each interrupt or signal. A handler is static iff it + -- is specified through the pragma Attach_Handler. + + User_Entry : array (Interrupt_ID) of Entry_Assoc := + (others => (T => Null_Task, E => Null_Task_Entry)); + pragma Volatile_Components (User_Entry); + -- Holds the task and entry index (if any) for each interrupt / signal + + -- Type and Head, Tail of the list containing Registered Interrupt + -- Handlers. These definitions are used to register the handlers + -- specified by the pragma Interrupt_Handler. + + type Registered_Handler; + type R_Link is access all Registered_Handler; + + type Registered_Handler is record + H : System.Address := System.Null_Address; + Next : R_Link := null; + end record; + + Registered_Handler_Head : R_Link := null; + Registered_Handler_Tail : R_Link := null; + + Server_ID : array (Interrupt_ID) of System.Tasking.Task_Id := + (others => System.Tasking.Null_Task); + pragma Atomic_Components (Server_ID); + -- Holds the Task_Id of the Server_Task for each interrupt / signal. + -- Task_Id is needed to accomplish locking per interrupt base. Also + -- is needed to determine whether to create a new Server_Task. + + Semaphore_ID_Map : array + (Interrupt_ID range 0 .. System.OS_Interface.Max_HW_Interrupt) of + Binary_Semaphore_Id := (others => 0); + -- Array of binary semaphores associated with vectored interrupts. Note + -- that the last bound should be Max_HW_Interrupt, but this will raise + -- Storage_Error if Num_HW_Interrupts is null so use extra 4 bytes instead. + + Interrupt_Access_Hold : Interrupt_Task_Access; + -- Variable for allocating an Interrupt_Server_Task + + Handler_Installed : array (HW_Interrupt) of Boolean := (others => False); + -- True if Notify_Interrupt was connected to the interrupt. Handlers can + -- be connected but disconnection is not possible on VxWorks. Therefore + -- we ensure Notify_Installed is connected at most once. + + ----------------------- + -- Local Subprograms -- + ----------------------- + + procedure Check_Reserved_Interrupt (Interrupt : Interrupt_ID); + -- Check if Id is a reserved interrupt, and if so raise Program_Error + -- with an appropriate message, otherwise return. + + procedure Finalize_Interrupt_Servers; + -- Unbind the handlers for hardware interrupt server tasks at program + -- termination. + + function Is_Registered (Handler : Parameterless_Handler) return Boolean; + -- See if Handler has been "pragma"ed using Interrupt_Handler. + -- Always consider a null handler as registered. + + procedure Notify_Interrupt (Param : System.Address); + pragma Convention (C, Notify_Interrupt); + -- Umbrella handler for vectored interrupts (not signals) + + procedure Install_Umbrella_Handler + (Interrupt : HW_Interrupt; + Handler : System.OS_Interface.Interrupt_Handler); + -- Install the runtime umbrella handler for a vectored hardware + -- interrupt + + procedure Unimplemented (Feature : String); + pragma No_Return (Unimplemented); + -- Used to mark a call to an unimplemented function. Raises Program_Error + -- with an appropriate message noting that Feature is unimplemented. + + -------------------- + -- Attach_Handler -- + -------------------- + + -- Calling this procedure with New_Handler = null and Static = True + -- means we want to detach the current handler regardless of the previous + -- handler's binding status (i.e. do not care if it is a dynamic or static + -- handler). + + -- This option is needed so that during the finalization of a PO, we can + -- detach handlers attached through pragma Attach_Handler. + + procedure Attach_Handler + (New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean := False) is + begin + Check_Reserved_Interrupt (Interrupt); + Interrupt_Manager.Attach_Handler (New_Handler, Interrupt, Static); + end Attach_Handler; + + ----------------------------- + -- Bind_Interrupt_To_Entry -- + ----------------------------- + + -- This procedure raises a Program_Error if it tries to + -- bind an interrupt to which an Entry or a Procedure is + -- already bound. + + procedure Bind_Interrupt_To_Entry + (T : Task_Id; + E : Task_Entry_Index; + Int_Ref : System.Address) + is + Interrupt : constant Interrupt_ID := + Interrupt_ID (Storage_Elements.To_Integer (Int_Ref)); + begin + Check_Reserved_Interrupt (Interrupt); + Interrupt_Manager.Bind_Interrupt_To_Entry (T, E, Interrupt); + end Bind_Interrupt_To_Entry; + + --------------------- + -- Block_Interrupt -- + --------------------- + + procedure Block_Interrupt (Interrupt : Interrupt_ID) is + begin + Unimplemented ("Block_Interrupt"); + end Block_Interrupt; + + ------------------------------ + -- Check_Reserved_Interrupt -- + ------------------------------ + + procedure Check_Reserved_Interrupt (Interrupt : Interrupt_ID) is + begin + if Is_Reserved (Interrupt) then + raise Program_Error with + "interrupt" & Interrupt_ID'Image (Interrupt) & " is reserved"; + else + return; + end if; + end Check_Reserved_Interrupt; + + --------------------- + -- Current_Handler -- + --------------------- + + function Current_Handler + (Interrupt : Interrupt_ID) return Parameterless_Handler + is + begin + Check_Reserved_Interrupt (Interrupt); + + -- ??? Since Parameterless_Handler is not Atomic, the current + -- implementation is wrong. We need a new service in Interrupt_Manager + -- to ensure atomicity. + + return User_Handler (Interrupt).H; + end Current_Handler; + + -------------------- + -- Detach_Handler -- + -------------------- + + -- Calling this procedure with Static = True means we want to Detach the + -- current handler regardless of the previous handler's binding status + -- (i.e. do not care if it is a dynamic or static handler). + + -- This option is needed so that during the finalization of a PO, we can + -- detach handlers attached through pragma Attach_Handler. + + procedure Detach_Handler + (Interrupt : Interrupt_ID; + Static : Boolean := False) + is + begin + Check_Reserved_Interrupt (Interrupt); + Interrupt_Manager.Detach_Handler (Interrupt, Static); + end Detach_Handler; + + ------------------------------ + -- Detach_Interrupt_Entries -- + ------------------------------ + + procedure Detach_Interrupt_Entries (T : Task_Id) is + begin + Interrupt_Manager.Detach_Interrupt_Entries (T); + end Detach_Interrupt_Entries; + + ---------------------- + -- Exchange_Handler -- + ---------------------- + + -- Calling this procedure with New_Handler = null and Static = True + -- means we want to detach the current handler regardless of the previous + -- handler's binding status (i.e. we do not care if it is a dynamic or + -- static handler). + + -- This option is needed so that during the finalization of a PO, we can + -- detach handlers attached through pragma Attach_Handler. + + procedure Exchange_Handler + (Old_Handler : out Parameterless_Handler; + New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean := False) + is + begin + Check_Reserved_Interrupt (Interrupt); + Interrupt_Manager.Exchange_Handler + (Old_Handler, New_Handler, Interrupt, Static); + end Exchange_Handler; + + -------------- + -- Finalize -- + -------------- + + procedure Finalize (Object : in out Static_Interrupt_Protection) is + begin + -- ??? loop to be executed only when we're not doing library level + -- finalization, since in this case all interrupt / signal tasks are + -- gone. + + if not Interrupt_Manager'Terminated then + for N in reverse Object.Previous_Handlers'Range loop + Interrupt_Manager.Attach_Handler + (New_Handler => Object.Previous_Handlers (N).Handler, + Interrupt => Object.Previous_Handlers (N).Interrupt, + Static => Object.Previous_Handlers (N).Static, + Restoration => True); + end loop; + end if; + + Tasking.Protected_Objects.Entries.Finalize + (Tasking.Protected_Objects.Entries.Protection_Entries (Object)); + end Finalize; + + -------------------------------- + -- Finalize_Interrupt_Servers -- + -------------------------------- + + -- Restore default handlers for interrupt servers + + -- This is called by the Interrupt_Manager task when it receives the abort + -- signal during program finalization. + + procedure Finalize_Interrupt_Servers is + HW_Interrupts : constant Boolean := HW_Interrupt'Last >= 0; + begin + if HW_Interrupts then + for Int in HW_Interrupt loop + if Server_ID (Interrupt_ID (Int)) /= null + and then + not Ada.Task_Identification.Is_Terminated + (To_Ada (Server_ID (Interrupt_ID (Int)))) + then + Interrupt_Manager.Attach_Handler + (New_Handler => null, + Interrupt => Interrupt_ID (Int), + Static => True, + Restoration => True); + end if; + end loop; + end if; + end Finalize_Interrupt_Servers; + + ------------------------------------- + -- Has_Interrupt_Or_Attach_Handler -- + ------------------------------------- + + function Has_Interrupt_Or_Attach_Handler + (Object : access Dynamic_Interrupt_Protection) + return Boolean + is + pragma Unreferenced (Object); + begin + return True; + end Has_Interrupt_Or_Attach_Handler; + + function Has_Interrupt_Or_Attach_Handler + (Object : access Static_Interrupt_Protection) + return Boolean + is + pragma Unreferenced (Object); + begin + return True; + end Has_Interrupt_Or_Attach_Handler; + + ---------------------- + -- Ignore_Interrupt -- + ---------------------- + + procedure Ignore_Interrupt (Interrupt : Interrupt_ID) is + begin + Unimplemented ("Ignore_Interrupt"); + end Ignore_Interrupt; + + ---------------------- + -- Install_Handlers -- + ---------------------- + + procedure Install_Handlers + (Object : access Static_Interrupt_Protection; + New_Handlers : New_Handler_Array) + is + begin + for N in New_Handlers'Range loop + + -- We need a lock around this ??? + + Object.Previous_Handlers (N).Interrupt := New_Handlers (N).Interrupt; + Object.Previous_Handlers (N).Static := User_Handler + (New_Handlers (N).Interrupt).Static; + + -- We call Exchange_Handler and not directly Interrupt_Manager. + -- Exchange_Handler so we get the Is_Reserved check. + + Exchange_Handler + (Old_Handler => Object.Previous_Handlers (N).Handler, + New_Handler => New_Handlers (N).Handler, + Interrupt => New_Handlers (N).Interrupt, + Static => True); + end loop; + end Install_Handlers; + + --------------------------------- + -- Install_Restricted_Handlers -- + --------------------------------- + + procedure Install_Restricted_Handlers + (Prio : Any_Priority; + Handlers : New_Handler_Array) + is + pragma Unreferenced (Prio); + begin + for N in Handlers'Range loop + Attach_Handler (Handlers (N).Handler, Handlers (N).Interrupt, True); + end loop; + end Install_Restricted_Handlers; + + ------------------------------ + -- Install_Umbrella_Handler -- + ------------------------------ + + procedure Install_Umbrella_Handler + (Interrupt : HW_Interrupt; + Handler : System.OS_Interface.Interrupt_Handler) + is + Vec : constant Interrupt_Vector := + Interrupt_Number_To_Vector (int (Interrupt)); + + Status : int; + + begin + -- Only install umbrella handler when no Ada handler has already been + -- installed. Note that the interrupt number is passed as a parameter + -- when an interrupt occurs, so the umbrella handler has a different + -- wrapper generated by intConnect for each interrupt number. + + if not Handler_Installed (Interrupt) then + Status := + Interrupt_Connect (Vec, Handler, System.Address (Interrupt)); + pragma Assert (Status = 0); + + Handler_Installed (Interrupt) := True; + end if; + end Install_Umbrella_Handler; + + ---------------- + -- Is_Blocked -- + ---------------- + + function Is_Blocked (Interrupt : Interrupt_ID) return Boolean is + begin + Unimplemented ("Is_Blocked"); + return False; + end Is_Blocked; + + ----------------------- + -- Is_Entry_Attached -- + ----------------------- + + function Is_Entry_Attached (Interrupt : Interrupt_ID) return Boolean is + begin + Check_Reserved_Interrupt (Interrupt); + return User_Entry (Interrupt).T /= Null_Task; + end Is_Entry_Attached; + + ------------------------- + -- Is_Handler_Attached -- + ------------------------- + + function Is_Handler_Attached (Interrupt : Interrupt_ID) return Boolean is + begin + Check_Reserved_Interrupt (Interrupt); + return User_Handler (Interrupt).H /= null; + end Is_Handler_Attached; + + ---------------- + -- Is_Ignored -- + ---------------- + + function Is_Ignored (Interrupt : Interrupt_ID) return Boolean is + begin + Unimplemented ("Is_Ignored"); + return False; + end Is_Ignored; + + ------------------- + -- Is_Registered -- + ------------------- + + function Is_Registered (Handler : Parameterless_Handler) return Boolean is + type Fat_Ptr is record + Object_Addr : System.Address; + Handler_Addr : System.Address; + end record; + + function To_Fat_Ptr is new Ada.Unchecked_Conversion + (Parameterless_Handler, Fat_Ptr); + + Ptr : R_Link; + Fat : Fat_Ptr; + + begin + if Handler = null then + return True; + end if; + + Fat := To_Fat_Ptr (Handler); + + Ptr := Registered_Handler_Head; + while Ptr /= null loop + if Ptr.H = Fat.Handler_Addr then + return True; + end if; + + Ptr := Ptr.Next; + end loop; + + return False; + end Is_Registered; + + ----------------- + -- Is_Reserved -- + ----------------- + + function Is_Reserved (Interrupt : Interrupt_ID) return Boolean is + use System.Interrupt_Management; + begin + return Reserve (System.Interrupt_Management.Interrupt_ID (Interrupt)); + end Is_Reserved; + + ---------------------- + -- Notify_Interrupt -- + ---------------------- + + -- Umbrella handler for vectored hardware interrupts (as opposed to signals + -- and exceptions). As opposed to the signal implementation, this handler + -- is installed in the vector table when the first Ada handler is attached + -- to the interrupt. However because VxWorks don't support disconnecting + -- handlers, this subprogram always test whether or not an Ada handler is + -- effectively attached. + + -- Otherwise, the handler that existed prior to program startup is in the + -- vector table. This ensures that handlers installed by the BSP are active + -- unless explicitly replaced in the program text. + + -- Each Interrupt_Server_Task has an associated binary semaphore on which + -- it pends once it's been started. This routine determines The appropriate + -- semaphore and issues a semGive call, waking the server task. When + -- a handler is unbound, System.Interrupts.Unbind_Handler issues a + -- Binary_Semaphore_Flush, and the server task deletes its semaphore + -- and terminates. + + procedure Notify_Interrupt (Param : System.Address) is + Interrupt : constant Interrupt_ID := Interrupt_ID (Param); + Id : constant Binary_Semaphore_Id := Semaphore_ID_Map (Interrupt); + Status : int; + begin + if Id /= 0 then + Status := Binary_Semaphore_Release (Id); + pragma Assert (Status = 0); + end if; + end Notify_Interrupt; + + --------------- + -- Reference -- + --------------- + + function Reference (Interrupt : Interrupt_ID) return System.Address is + begin + Check_Reserved_Interrupt (Interrupt); + return Storage_Elements.To_Address + (Storage_Elements.Integer_Address (Interrupt)); + end Reference; + + -------------------------------- + -- Register_Interrupt_Handler -- + -------------------------------- + + procedure Register_Interrupt_Handler (Handler_Addr : System.Address) is + New_Node_Ptr : R_Link; + + begin + -- This routine registers a handler as usable for dynamic interrupt + -- handler association. Routines attaching and detaching handlers + -- dynamically should determine whether the handler is registered. + -- Program_Error should be raised if it is not registered. + + -- Pragma Interrupt_Handler can only appear in a library level PO + -- definition and instantiation. Therefore, we do not need to implement + -- an unregister operation. Nor do we need to protect the queue + -- structure with a lock. + + pragma Assert (Handler_Addr /= System.Null_Address); + + New_Node_Ptr := new Registered_Handler; + New_Node_Ptr.H := Handler_Addr; + + if Registered_Handler_Head = null then + Registered_Handler_Head := New_Node_Ptr; + Registered_Handler_Tail := New_Node_Ptr; + else + Registered_Handler_Tail.Next := New_Node_Ptr; + Registered_Handler_Tail := New_Node_Ptr; + end if; + end Register_Interrupt_Handler; + + ----------------------- + -- Unblock_Interrupt -- + ----------------------- + + procedure Unblock_Interrupt (Interrupt : Interrupt_ID) is + begin + Unimplemented ("Unblock_Interrupt"); + end Unblock_Interrupt; + + ------------------ + -- Unblocked_By -- + ------------------ + + function Unblocked_By + (Interrupt : Interrupt_ID) return System.Tasking.Task_Id + is + begin + Unimplemented ("Unblocked_By"); + return Null_Task; + end Unblocked_By; + + ------------------------ + -- Unignore_Interrupt -- + ------------------------ + + procedure Unignore_Interrupt (Interrupt : Interrupt_ID) is + begin + Unimplemented ("Unignore_Interrupt"); + end Unignore_Interrupt; + + ------------------- + -- Unimplemented -- + ------------------- + + procedure Unimplemented (Feature : String) is + begin + raise Program_Error with Feature & " not implemented on VxWorks"; + end Unimplemented; + + ----------------------- + -- Interrupt_Manager -- + ----------------------- + + task body Interrupt_Manager is + -- By making this task independent of any master, when the process goes + -- away, the Interrupt_Manager will terminate gracefully. + + Ignore : constant Boolean := System.Tasking.Utilities.Make_Independent; + pragma Unreferenced (Ignore); + + -------------------- + -- Local Routines -- + -------------------- + + procedure Bind_Handler (Interrupt : Interrupt_ID); + -- This procedure does not do anything if a signal is blocked. + -- Otherwise, we have to interrupt Server_Task for status change + -- through a wakeup signal. + + procedure Unbind_Handler (Interrupt : Interrupt_ID); + -- This procedure does not do anything if a signal is blocked. + -- Otherwise, we have to interrupt Server_Task for status change + -- through an abort signal. + + procedure Unprotected_Exchange_Handler + (Old_Handler : out Parameterless_Handler; + New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean; + Restoration : Boolean := False); + + procedure Unprotected_Detach_Handler + (Interrupt : Interrupt_ID; + Static : Boolean); + + ------------------ + -- Bind_Handler -- + ------------------ + + procedure Bind_Handler (Interrupt : Interrupt_ID) is + begin + Install_Umbrella_Handler + (HW_Interrupt (Interrupt), Notify_Interrupt'Access); + end Bind_Handler; + + -------------------- + -- Unbind_Handler -- + -------------------- + + procedure Unbind_Handler (Interrupt : Interrupt_ID) is + Status : int; + + begin + -- Flush server task off semaphore, allowing it to terminate + + Status := Binary_Semaphore_Flush (Semaphore_ID_Map (Interrupt)); + pragma Assert (Status = 0); + end Unbind_Handler; + + -------------------------------- + -- Unprotected_Detach_Handler -- + -------------------------------- + + procedure Unprotected_Detach_Handler + (Interrupt : Interrupt_ID; + Static : Boolean) + is + Old_Handler : Parameterless_Handler; + begin + if User_Entry (Interrupt).T /= Null_Task then + + -- If an interrupt entry is installed raise Program_Error + -- (propagate it to the caller). + + raise Program_Error with + "an interrupt entry is already installed"; + end if; + + -- Note : Static = True will pass the following check. This is the + -- case when we want to detach a handler regardless of the static + -- status of the Current_Handler. + + if not Static and then User_Handler (Interrupt).Static then + + -- Trying to detach a static Interrupt Handler, raise + -- Program_Error. + + raise Program_Error with + "trying to detach a static Interrupt Handler"; + end if; + + Old_Handler := User_Handler (Interrupt).H; + + -- The new handler + + User_Handler (Interrupt).H := null; + User_Handler (Interrupt).Static := False; + + if Old_Handler /= null then + Unbind_Handler (Interrupt); + end if; + end Unprotected_Detach_Handler; + + ---------------------------------- + -- Unprotected_Exchange_Handler -- + ---------------------------------- + + procedure Unprotected_Exchange_Handler + (Old_Handler : out Parameterless_Handler; + New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean; + Restoration : Boolean := False) + is + begin + if User_Entry (Interrupt).T /= Null_Task then + + -- If an interrupt entry is already installed, raise + -- Program_Error (propagate it to the caller). + + raise Program_Error with "an interrupt is already installed"; + end if; + + -- Note : A null handler with Static = True will pass the following + -- check. This is the case when we want to detach a handler + -- regardless of the Static status of Current_Handler. + + -- We don't check anything if Restoration is True, since we may be + -- detaching a static handler to restore a dynamic one. + + if not Restoration and then not Static + and then (User_Handler (Interrupt).Static + + -- Trying to overwrite a static Interrupt Handler with a dynamic + -- Handler + + -- The new handler is not specified as an Interrupt Handler by a + -- pragma. + + or else not Is_Registered (New_Handler)) + then + raise Program_Error with + "trying to overwrite a static interrupt handler with a " + & "dynamic handler"; + end if; + + -- Save the old handler + + Old_Handler := User_Handler (Interrupt).H; + + -- The new handler + + User_Handler (Interrupt).H := New_Handler; + + if New_Handler = null then + + -- The null handler means we are detaching the handler + + User_Handler (Interrupt).Static := False; + + else + User_Handler (Interrupt).Static := Static; + end if; + + -- Invoke a corresponding Server_Task if not yet created. Place + -- Task_Id info in Server_ID array. + + if New_Handler /= null + and then + (Server_ID (Interrupt) = Null_Task + or else + Ada.Task_Identification.Is_Terminated + (To_Ada (Server_ID (Interrupt)))) + then + Interrupt_Access_Hold := + new Interrupt_Server_Task (Interrupt, Binary_Semaphore_Create); + Server_ID (Interrupt) := + To_System (Interrupt_Access_Hold.all'Identity); + end if; + + if (New_Handler = null) and then Old_Handler /= null then + + -- Restore default handler + + Unbind_Handler (Interrupt); + + elsif Old_Handler = null then + + -- Save default handler + + Bind_Handler (Interrupt); + end if; + end Unprotected_Exchange_Handler; + + -- Start of processing for Interrupt_Manager + + begin + loop + -- A block is needed to absorb Program_Error exception + + declare + Old_Handler : Parameterless_Handler; + + begin + select + accept Attach_Handler + (New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean; + Restoration : Boolean := False) + do + Unprotected_Exchange_Handler + (Old_Handler, New_Handler, Interrupt, Static, Restoration); + end Attach_Handler; + + or + accept Exchange_Handler + (Old_Handler : out Parameterless_Handler; + New_Handler : Parameterless_Handler; + Interrupt : Interrupt_ID; + Static : Boolean) + do + Unprotected_Exchange_Handler + (Old_Handler, New_Handler, Interrupt, Static); + end Exchange_Handler; + + or + accept Detach_Handler + (Interrupt : Interrupt_ID; + Static : Boolean) + do + Unprotected_Detach_Handler (Interrupt, Static); + end Detach_Handler; + + or + accept Bind_Interrupt_To_Entry + (T : Task_Id; + E : Task_Entry_Index; + Interrupt : Interrupt_ID) + do + -- If there is a binding already (either a procedure or an + -- entry), raise Program_Error (propagate it to the caller). + + if User_Handler (Interrupt).H /= null + or else User_Entry (Interrupt).T /= Null_Task + then + raise Program_Error with + "a binding for this interrupt is already present"; + end if; + + User_Entry (Interrupt) := Entry_Assoc'(T => T, E => E); + + -- Indicate the attachment of interrupt entry in the ATCB. + -- This is needed so when an interrupt entry task terminates + -- the binding can be cleaned. The call to unbinding must be + -- make by the task before it terminates. + + T.Interrupt_Entry := True; + + -- Invoke a corresponding Server_Task if not yet created. + -- Place Task_Id info in Server_ID array. + + if Server_ID (Interrupt) = Null_Task + or else + Ada.Task_Identification.Is_Terminated + (To_Ada (Server_ID (Interrupt))) + then + Interrupt_Access_Hold := new Interrupt_Server_Task + (Interrupt, Binary_Semaphore_Create); + Server_ID (Interrupt) := + To_System (Interrupt_Access_Hold.all'Identity); + end if; + + Bind_Handler (Interrupt); + end Bind_Interrupt_To_Entry; + + or + accept Detach_Interrupt_Entries (T : Task_Id) do + for Int in Interrupt_ID'Range loop + if not Is_Reserved (Int) then + if User_Entry (Int).T = T then + User_Entry (Int) := + Entry_Assoc' + (T => Null_Task, E => Null_Task_Entry); + Unbind_Handler (Int); + end if; + end if; + end loop; + + -- Indicate in ATCB that no interrupt entries are attached + + T.Interrupt_Entry := False; + end Detach_Interrupt_Entries; + end select; + + exception + -- If there is a Program_Error we just want to propagate it to + -- the caller and do not want to stop this task. + + when Program_Error => + null; + + when others => + pragma Assert (False); + null; + end; + end loop; + + exception + when Standard'Abort_Signal => + + -- Flush interrupt server semaphores, so they can terminate + + Finalize_Interrupt_Servers; + raise; + end Interrupt_Manager; + + --------------------------- + -- Interrupt_Server_Task -- + --------------------------- + + -- Server task for vectored hardware interrupt handling + + task body Interrupt_Server_Task is + Ignore : constant Boolean := System.Tasking.Utilities.Make_Independent; + + Self_Id : constant Task_Id := Self; + Tmp_Handler : Parameterless_Handler; + Tmp_ID : Task_Id; + Tmp_Entry_Index : Task_Entry_Index; + Status : int; + + begin + Semaphore_ID_Map (Interrupt) := Int_Sema; + + loop + -- Pend on semaphore that will be triggered by the umbrella handler + -- when the associated interrupt comes in. + + Status := Binary_Semaphore_Obtain (Int_Sema); + pragma Assert (Status = 0); + + if User_Handler (Interrupt).H /= null then + + -- Protected procedure handler + + Tmp_Handler := User_Handler (Interrupt).H; + Tmp_Handler.all; + + elsif User_Entry (Interrupt).T /= Null_Task then + + -- Interrupt entry handler + + Tmp_ID := User_Entry (Interrupt).T; + Tmp_Entry_Index := User_Entry (Interrupt).E; + System.Tasking.Rendezvous.Call_Simple + (Tmp_ID, Tmp_Entry_Index, System.Null_Address); + + else + -- Semaphore has been flushed by an unbind operation in the + -- Interrupt_Manager. Terminate the server task. + + -- Wait for the Interrupt_Manager to complete its work + + POP.Write_Lock (Self_Id); + + -- Unassociate the interrupt handler + + Semaphore_ID_Map (Interrupt) := 0; + + -- Delete the associated semaphore + + Status := Binary_Semaphore_Delete (Int_Sema); + + pragma Assert (Status = 0); + + -- Set status for the Interrupt_Manager + + Server_ID (Interrupt) := Null_Task; + POP.Unlock (Self_Id); + + exit; + end if; + end loop; + end Interrupt_Server_Task; + +begin + -- Get Interrupt_Manager's ID so that Abort_Interrupt can be sent + + Interrupt_Manager_ID := To_System (Interrupt_Manager'Identity); +end System.Interrupts; diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 213587e..81aed5c 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2094,7 +2094,7 @@ cgraph_node::dump (FILE *f) fprintf (f, " Function flags:"); if (count.initialized_p ()) { - fprintf (f, " profile_count "); + fprintf (f, " count: "); count.dump (f); } if (origin) @@ -2172,10 +2172,13 @@ cgraph_node::dump (FILE *f) fprintf (f, " Called by: "); + profile_count sum = profile_count::zero (); for (edge = callers; edge; edge = edge->next_caller) { fprintf (f, "%s ", edge->caller->dump_name ()); edge->dump_edge_flags (f); + if (edge->count.initialized_p ()) + sum += edge->count; } fprintf (f, "\n Calls: "); @@ -2186,6 +2189,36 @@ cgraph_node::dump (FILE *f) } fprintf (f, "\n"); + if (count.initialized_p ()) + { + bool ok = true; + bool min = false; + ipa_ref *ref; + + FOR_EACH_ALIAS (this, ref) + if (dyn_cast <cgraph_node *> (ref->referring)->count.initialized_p ()) + sum += dyn_cast <cgraph_node *> (ref->referring)->count; + + if (global.inlined_to + || (symtab->state < EXPANSION + && ultimate_alias_target () == this && only_called_directly_p ())) + ok = !count.differs_from_p (sum); + else if (count > profile_count::from_gcov_type (100) + && count < sum.apply_scale (99, 100)) + ok = false, min = true; + if (!ok) + { + fprintf (f, " Invalid sum of caller counts "); + sum.dump (f); + if (min) + fprintf (f, ", should be at most "); + else + fprintf (f, ", should be "); + count.dump (f); + fprintf (f, "\n"); + } + } + for (edge = indirect_calls; edge; edge = edge->next_callee) { if (edge->indirect_info->polymorphic) diff --git a/gcc/combine.c b/gcc/combine.c index 39ef3c6..2d49bc2 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -9634,7 +9634,7 @@ make_field_assignment (rtx x) other, pos), dest); src = force_to_mode (src, mode, - GET_MODE_PRECISION (mode) >= HOST_BITS_PER_WIDE_INT + len >= HOST_BITS_PER_WIDE_INT ? HOST_WIDE_INT_M1U : (HOST_WIDE_INT_1U << len) - 1, 0); diff --git a/gcc/config.gcc b/gcc/config.gcc index a311cd95..8b00e66 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -917,6 +917,8 @@ case ${target} in xm_defines=POSIX extra_options="${extra_options} vxworks.opt" extra_objs="$extra_objs vxworks.o" + use_gcc_stdint=provide + tm_file="${tm_file} vxworks-stdint.h" case ${enable_threads} in no) ;; "" | yes | vxworks) thread_file='vxworks' ;; @@ -2388,13 +2390,13 @@ powerpc-*-eabispe*) use_gcc_stdint=wrap ;; powerpc-*-eabisimaltivec*) - tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h rs6000/eabisim.h rs6000/eabialtivec.h" + tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h rs6000/eabialtivec.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcendian rs6000/t-ppccomm" use_gcc_stdint=wrap ;; powerpc-*-eabisim*) - tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h rs6000/eabisim.h" + tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" use_gcc_stdint=wrap @@ -2405,7 +2407,7 @@ powerpc-*-elf*) tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" ;; powerpc-*-eabialtivec*) - tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h rs6000/eabialtivec.h" + tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabialtivec.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcendian rs6000/t-ppccomm" use_gcc_stdint=wrap @@ -2417,7 +2419,7 @@ powerpc-xilinx-eabi*) use_gcc_stdint=wrap ;; powerpc-*-eabi*) - tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h" + tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" use_gcc_stdint=wrap @@ -2428,7 +2430,7 @@ powerpc-*-rtems*spe*) tmake_file="${tmake_file} powerpcspe/t-fprules powerpcspe/t-rtems powerpcspe/t-ppccomm" ;; powerpc-*-rtems*) - tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/e500.h rs6000/rtems.h rtems.h" + tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/rtems.h rtems.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm" ;; @@ -2544,15 +2546,15 @@ powerpc-wrs-vxworks|powerpc-wrs-vxworksae|powerpc-wrs-vxworksmils) extra_headers=ppc-asm.h case ${target} in *-vxworksmils*) - tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/e500.h rs6000/vxworksmils.h" + tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/vxworksmils.h" tmake_file="${tmake_file} rs6000/t-vxworksmils" ;; *-vxworksae*) - tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/e500.h rs6000/vxworksae.h" + tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/vxworksae.h" tmake_file="${tmake_file} rs6000/t-vxworksae" ;; *-vxworks*) - tm_file="${tm_file} vx-common.h vxworks.h rs6000/vxworks.h rs6000/e500.h" + tm_file="${tm_file} vx-common.h vxworks.h rs6000/vxworks.h" ;; esac ;; @@ -2571,13 +2573,13 @@ powerpcle-*-elf*) extra_options="${extra_options} rs6000/sysv4.opt" ;; powerpcle-*-eabisim*) - tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/e500.h rs6000/eabisim.h" + tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/eabisim.h" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" extra_options="${extra_options} rs6000/sysv4.opt" use_gcc_stdint=wrap ;; powerpcle-*-eabi*) - tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/e500.h" + tm_file="${tm_file} dbxelf.h elfos.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" extra_options="${extra_options} rs6000/sysv4.opt" use_gcc_stdint=wrap diff --git a/gcc/config/avr/avr-arch.h b/gcc/config/avr/avr-arch.h index 9463735..e38345b 100644 --- a/gcc/config/avr/avr-arch.h +++ b/gcc/config/avr/avr-arch.h @@ -41,6 +41,7 @@ enum avr_arch_id ARCH_AVR6, ARCH_AVRTINY, ARCH_AVRXMEGA2, + ARCH_AVRXMEGA3, ARCH_AVRXMEGA4, ARCH_AVRXMEGA5, ARCH_AVRXMEGA6, @@ -86,6 +87,9 @@ typedef struct /* Default start of data section address for architecture. */ int default_data_section_start; + /* Offset where flash memory is seen in RAM address range or 0. */ + int flash_pm_offset; + /* Offset between SFR address and RAM address: SFR-address = RAM-address - sfr_offset */ int sfr_offset; @@ -150,7 +154,16 @@ AVR_ERRATA_SKIP For information please refer the following respective errata links http://www.atmel.com/dyn/resources/prod_documents/doc2494.pdf - http://www.atmel.com/dyn/resources/prod_documents/doc1436.pdf */ + http://www.atmel.com/dyn/resources/prod_documents/doc1436.pdf + +AVR_ISA_RCALL + Always use RJMP / RCALL and assume JMP / CALL are not available. + This affects multilib selection via specs generation and -mshort-calls. + Even if a device like ATtiny417 from avrxmega3 supports JMP / CALL, we + assume these instructions are not available and we set the built-in + macro __AVR_HAVE_JMP_CALL__ accordingly. This macro is used to + determine a rough estimate of flash size in libgcc, and AVR-LibC uses + this macro to determine vector sizes. */ enum avr_device_specific_features { @@ -158,8 +171,10 @@ enum avr_device_specific_features AVR_ISA_RMW = 0x1, /* device has RMW instructions. */ AVR_SHORT_SP = 0x2, /* Stack Pointer has 8 bits width. */ AVR_ERRATA_SKIP = 0x4, /* device has a core erratum. */ - AVR_ISA_LDS = 0x8 /* whether LDS / STS is valid for all data in static + AVR_ISA_LDS = 0x8, /* whether LDS / STS is valid for all data in static storage. Only useful for reduced Tiny. */ + AVR_ISA_RCALL = 0x10 /* Use RJMP / RCALL even though JMP / CALL + are available (-mshort-calls). */ }; /* Map architecture to its texinfo string. */ diff --git a/gcc/config/avr/avr-c.c b/gcc/config/avr/avr-c.c index 9a3a190..81ffc4e 100644 --- a/gcc/config/avr/avr-c.c +++ b/gcc/config/avr/avr-c.c @@ -313,11 +313,16 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile) cpp_define (pfile, "__AVR_ENHANCED__"); cpp_define (pfile, "__AVR_HAVE_MUL__"); } + + if (AVR_HAVE_JMP_CALL) + cpp_define (pfile, "__AVR_HAVE_JMP_CALL__"); + if (avr_arch->have_jmp_call) - { - cpp_define (pfile, "__AVR_MEGA__"); - cpp_define (pfile, "__AVR_HAVE_JMP_CALL__"); - } + cpp_define (pfile, "__AVR_MEGA__"); + + if (AVR_SHORT_CALLS) + cpp_define (pfile, "__AVR_SHORT_CALLS__"); + if (AVR_XMEGA) cpp_define (pfile, "__AVR_XMEGA__"); @@ -335,9 +340,13 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile) (ATtiny4/5/9/10/20 and 40) mapped program memory starts at 0x4000. */ cpp_define_formatted (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x%x", - AVR_TINY_PM_OFFSET); + avr_arch->flash_pm_offset); } + if (avr_arch->flash_pm_offset) + cpp_define_formatted (pfile, "__AVR_PM_BASE_ADDRESS__=0x%x", + avr_arch->flash_pm_offset); + if (AVR_HAVE_EIJMP_EICALL) { cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__"); diff --git a/gcc/config/avr/avr-devices.c b/gcc/config/avr/avr-devices.c index ad92e97..c391ef9 100644 --- a/gcc/config/avr/avr-devices.c +++ b/gcc/config/avr/avr-devices.c @@ -34,30 +34,31 @@ const avr_arch_t avr_arch_types[] = { /* unknown device specified */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, AVR_MMCU_DEFAULT }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, NULL, AVR_MMCU_DEFAULT }, /* - A M J LM E E E X R T d S S O A - S U M PO L L I M A I a t F ff r - M L P MV P P J E M N t a R s c - XW M M M G P Y a r e h - X P A D t t ID */ - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1", "avr1" }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2", "avr2" }, - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "25", "avr25" }, - { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3", "avr3" }, - { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "31", "avr31" }, - { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "35", "avr35" }, - { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "4", "avr4" }, - { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "5", "avr5" }, - { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 32, "51", "avr51" }, - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "6", "avr6" }, - - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040, 0, "100", "avrtiny" }, - { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0, "102", "avrxmega2" }, - { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000, 0, "104", "avrxmega4" }, - { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000, 0, "105", "avrxmega5" }, - { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000, 0, "106", "avrxmega6" }, - { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, "107", "avrxmega7" } + A M J LM E E E X R T d S FPO S O A + S U M PO L L I M A I a t lMff F ff r + M L P MV P P J E M N t a a s R s c + XW M M M G P Y a r s e e h + X P A D t h t t ID */ + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "1", "avr1" }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "2", "avr2" }, + { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "25", "avr25" }, + { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "3", "avr3" }, + { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 0, 32, "31", "avr31" }, + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "35", "avr35" }, + { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "4", "avr4" }, + { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0, 32, "5", "avr5" }, + { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 0, 32, "51", "avr51" }, + { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 0, 32, "6", "avr6" }, + + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040, 0x4000, 0, "100", "avrtiny" }, + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0, 0, "102", "avrxmega2" }, + { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0x8000, 0, "103", "avrxmega3" }, + { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000, 0, 0, "104", "avrxmega4" }, + { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000, 0, 0, "105", "avrxmega5" }, + { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000, 0, 0, "106", "avrxmega6" }, + { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, 0, "107", "avrxmega7" } }; const avr_arch_info_t @@ -95,6 +96,9 @@ avr_texinfo[] = { ARCH_AVRXMEGA2, "``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB " "of program memory." }, + { ARCH_AVRXMEGA3, + "``XMEGA'' devices with up to 64@tie{}KiB of combined program memory " + "and RAM, and with program memory visible in the RAM address space." }, { ARCH_AVRXMEGA4, "``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB " "of program memory." }, diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def index 68d0d81..08a8b69 100644 --- a/gcc/config/avr/avr-mcus.def +++ b/gcc/config/avr/avr-mcus.def @@ -299,6 +299,23 @@ AVR_MCU ("atxmega16c4", ARCH_AVRXMEGA2, AVR_ISA_RMW, "__AVR_ATxmega16C4__" AVR_MCU ("atxmega32a4u", ARCH_AVRXMEGA2, AVR_ISA_RMW, "__AVR_ATxmega32A4U__", 0x2000, 0x0, 0x9000) AVR_MCU ("atxmega32c4", ARCH_AVRXMEGA2, AVR_ISA_RMW, "__AVR_ATxmega32C4__", 0x2000, 0x0, 0x9000) AVR_MCU ("atxmega32e5", ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_ATxmega32E5__", 0x2000, 0x0, 0x9000) +/* Xmega, Flash + RAM < 64K, flash visible in RAM address space */ +AVR_MCU ("avrxmega3", ARCH_AVRXMEGA3, AVR_ISA_NONE, NULL, 0x3f00, 0x0, 0x8000) +AVR_MCU ("attiny212", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny212__", 0x3f80, 0x0, 0x800) +AVR_MCU ("attiny214", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny214__", 0x3f80, 0x0, 0x800) +AVR_MCU ("attiny412", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny412__", 0x3f00, 0x0, 0x1000) +AVR_MCU ("attiny414", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny414__", 0x3f00, 0x0, 0x1000) +AVR_MCU ("attiny416", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny416__", 0x3f00, 0x0, 0x1000) +AVR_MCU ("attiny417", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny417__", 0x3f00, 0x0, 0x1000) +AVR_MCU ("attiny814", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny814__", 0x3e00, 0x0, 0x2000) +AVR_MCU ("attiny816", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny816__", 0x3e00, 0x0, 0x2000) +AVR_MCU ("attiny817", ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny817__", 0x3e00, 0x0, 0x2000) +AVR_MCU ("attiny1614", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny1614__", 0x3800, 0x0, 0x4000) +AVR_MCU ("attiny1616", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny1616__", 0x3800, 0x0, 0x4000) +AVR_MCU ("attiny1617", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny1617__", 0x3800, 0x0, 0x4000) +AVR_MCU ("attiny3214", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny3214__", 0x3800, 0x0, 0x8000) +AVR_MCU ("attiny3216", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny3216__", 0x3800, 0x0, 0x8000) +AVR_MCU ("attiny3217", ARCH_AVRXMEGA3, AVR_ISA_NONE, "__AVR_ATtiny3217__", 0x3800, 0x0, 0x8000) /* Xmega, 64K < Flash <= 128K, RAM <= 64K */ AVR_MCU ("avrxmega4", ARCH_AVRXMEGA4, AVR_ISA_NONE, NULL, 0x2000, 0x0, 0x11000) AVR_MCU ("atxmega64a3", ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_ATxmega64A3__", 0x2000, 0x0, 0x11000) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 648a125..4f385d5 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -2502,7 +2502,7 @@ avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr) if (AVR_TINY && avr_address_tiny_pm_p (addr)) { - addr = plus_constant (Pmode, addr, AVR_TINY_PM_OFFSET); + addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset); } switch (GET_CODE (addr)) @@ -9398,7 +9398,7 @@ avr_assemble_integer (rtx x, unsigned int size, int aligned_p) if (AVR_TINY && avr_address_tiny_pm_p (x)) { - x = plus_constant (Pmode, x, AVR_TINY_PM_OFFSET); + x = plus_constant (Pmode, x, avr_arch->flash_pm_offset); } return default_assemble_integer (x, size, aligned_p); @@ -9998,9 +9998,11 @@ static void avr_asm_init_sections (void) { /* Override section callbacks to keep track of `avr_need_clear_bss_p' - resp. `avr_need_copy_data_p'. */ + resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then + we have also to track .rodata because it is located in RAM then. */ - readonly_data_section->unnamed.callback = avr_output_data_section_asm_op; + if (0 == avr_arch->flash_pm_offset) + readonly_data_section->unnamed.callback = avr_output_data_section_asm_op; data_section->unnamed.callback = avr_output_data_section_asm_op; bss_section->unnamed.callback = avr_output_bss_section_asm_op; } @@ -10032,9 +10034,13 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl) if (!avr_need_copy_data_p) avr_need_copy_data_p = (STR_PREFIX_P (name, ".data") - || STR_PREFIX_P (name, ".rodata") || STR_PREFIX_P (name, ".gnu.linkonce.d")); + if (!avr_need_copy_data_p + && 0 == avr_arch->flash_pm_offset) + avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata") + || STR_PREFIX_P (name, ".gnu.linkonce.r")); + if (!avr_need_clear_bss_p) avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss"); @@ -10201,7 +10207,7 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p) if (progmem_p) { - // Tag symbols for later addition of 0x4000 (AVR_TINY_PM_OFFSET). + // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset). SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM; } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 3dfa8c3..3158887 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -60,7 +60,9 @@ enum #define TARGET_CPU_CPP_BUILTINS() avr_cpu_cpp_builtins (pfile) -#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call) +#define AVR_SHORT_CALLS (TARGET_SHORT_CALLS \ + && avr_arch == &avr_arch_types[ARCH_AVRXMEGA3]) +#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call && ! AVR_SHORT_CALLS) #define AVR_HAVE_MUL (avr_arch->have_mul) #define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx) #define AVR_HAVE_LPM (!AVR_TINY) @@ -74,8 +76,6 @@ enum || avr_arch->have_rampd) #define AVR_HAVE_EIJMP_EICALL (avr_arch->have_eijmp_eicall) -#define AVR_TINY_PM_OFFSET (0x4000) - /* Handling of 8-bit SP versus 16-bit SP is as follows: FIXME: DRIVER_SELF_SPECS has changed. diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt index a1edec9..1efb1c0 100644 --- a/gcc/config/avr/avr.opt +++ b/gcc/config/avr/avr.opt @@ -44,6 +44,10 @@ Target Report Undocumented Mask(ALL_DEBUG) mlog= Target RejectNegative Joined Undocumented Var(avr_log_details) +mshort-calls +Target Report RejectNegative Mask(SHORT_CALLS) +Use RJMP / RCALL even though CALL / JMP are available. + mint8 Target Report Mask(INT8) Use an 8-bit 'int' type. diff --git a/gcc/config/avr/gen-avr-mmcu-specs.c b/gcc/config/avr/gen-avr-mmcu-specs.c index 4cf9114..db17eeb 100644 --- a/gcc/config/avr/gen-avr-mmcu-specs.c +++ b/gcc/config/avr/gen-avr-mmcu-specs.c @@ -113,6 +113,7 @@ static void print_mcu (const avr_mcu_t *mcu) { const char *sp8_spec; + const char *rcall_spec; const avr_mcu_t *arch_mcu; const avr_arch_t *arch; enum avr_arch_id arch_id = mcu->arch_id; @@ -134,6 +135,7 @@ print_mcu (const avr_mcu_t *mcu) bool errata_skip = 0 != (mcu->dev_attribute & AVR_ERRATA_SKIP); bool rmw = 0 != (mcu->dev_attribute & AVR_ISA_RMW); bool sp8 = 0 != (mcu->dev_attribute & AVR_SHORT_SP); + bool rcall = (mcu->dev_attribute & AVR_ISA_RCALL); bool is_arch = NULL == mcu->macro; bool is_device = ! is_arch; @@ -150,13 +152,25 @@ print_mcu (const avr_mcu_t *mcu) sp8_spec = sp8 ? "-msp8" :"%<msp8"; } + if (is_arch + && ARCH_AVRXMEGA3 == arch_id) + { + // Leave "avrxmega3" alone. This architectures is the only one + // that mixes devices with and without JMP / CALL. + rcall_spec = ""; + } + else + { + rcall_spec = rcall ? "-mshort-calls" : "%<mshort-calls"; + } + fprintf (f, "#\n" "# Auto-generated specs for AVR "); if (is_arch) fprintf (f, "core architecture %s\n", arch->name); else - fprintf (f, "device %s (core %s, %d-bit SP)\n", - mcu->name, arch->name, sp8 ? 8 : 16); + fprintf (f, "device %s (core %s, %d-bit SP%s)\n", mcu->name, + arch->name, sp8 ? 8 : 16, rcall ? ", short-calls" : ""); fprintf (f, "%s\n", header); if (is_device) @@ -255,6 +269,7 @@ print_mcu (const avr_mcu_t *mcu) { fprintf (f, "*self_spec:\n"); fprintf (f, "\t%%{!mmcu=avr*: %%<mmcu=* -mmcu=%s} ", arch->name); + fprintf (f, "%s ", rcall_spec); fprintf (f, "%s\n\n", sp8_spec); #if defined (WITH_AVRLIBC) diff --git a/gcc/config/avr/genmultilib.awk b/gcc/config/avr/genmultilib.awk index 2451087..e657e55 100644 --- a/gcc/config/avr/genmultilib.awk +++ b/gcc/config/avr/genmultilib.awk @@ -35,6 +35,9 @@ BEGIN { dir_tiny = "tiny-stack" opt_tiny = "msp8" + dir_rcall = "short-calls" + opt_rcall = "mshort-calls" + # awk Variable Makefile Variable # ------------------------------------------ # m_options <-> MULTILIB_OPTIONS @@ -116,6 +119,8 @@ BEGIN { { if (dev_attribute[i] == "AVR_SHORT_SP") opts = opts "/" opt_tiny + if (dev_attribute[i] == "AVR_ISA_RCALL") + opts = opts "/" opt_rcall } if (!have[opts]) @@ -140,7 +145,7 @@ END { # Intended Target: ./gcc/config/avr/t-multilib - print m_options " " opt_tiny - print m_dirnames " " dir_tiny + print m_options " " opt_tiny " " opt_rcall + print m_dirnames " " dir_tiny " " dir_rcall print m_required } diff --git a/gcc/config/avr/t-multilib b/gcc/config/avr/t-multilib index dbbf3bc..6a6eebc 100644 --- a/gcc/config/avr/t-multilib +++ b/gcc/config/avr/t-multilib @@ -21,9 +21,9 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. -MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8 +MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega3/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8 mshort-calls -MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack +MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack short-calls MULTILIB_REQUIRED = \ msp8 \ @@ -37,6 +37,8 @@ MULTILIB_REQUIRED = \ mmcu=avr51 \ mmcu=avr6 \ mmcu=avrxmega2 \ + mmcu=avrxmega3/mshort-calls \ + mmcu=avrxmega3 \ mmcu=avrxmega4 \ mmcu=avrxmega5 \ mmcu=avrxmega6 \ diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 737bdb3..5c5096b 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -7098,7 +7098,10 @@ (define_expand "return" [(return)] "sparc_can_use_return_insn_p ()" - "") +{ + if (cfun->calls_alloca) + emit_insn (gen_frame_blockage ()); +}) (define_insn "*return_internal" [(return)] diff --git a/gcc/config/vxworks-stdint.h b/gcc/config/vxworks-stdint.h new file mode 100644 index 0000000..2595e83 --- /dev/null +++ b/gcc/config/vxworks-stdint.h @@ -0,0 +1,53 @@ +/* Definitions for <stdint.h> types on systems using VxWorks. + Copyright (C) 2017 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#define SIG_ATOMIC_TYPE "unsigned char" + +#define INT8_TYPE "signed char" +#define INT16_TYPE "short int" +#define INT32_TYPE "int" +#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int") +#define UINT8_TYPE "unsigned char" +#define UINT16_TYPE "short unsigned int" +#define UINT32_TYPE "unsigned int" +#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int") +#define INT_LEAST8_TYPE "signed char" +#define INT_LEAST16_TYPE "short int" +#define INT_LEAST32_TYPE "int" +#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int") +#define UINT_LEAST8_TYPE "unsigned char" +#define UINT_LEAST16_TYPE "short unsigned int" +#define UINT_LEAST32_TYPE "unsigned int" +#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int") +#define INT_FAST8_TYPE "signed char" +#define INT_FAST16_TYPE "int" +#define INT_FAST32_TYPE "int" +#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int") +#define UINT_FAST8_TYPE "unsigned char" +#define UINT_FAST16_TYPE "unsigned int" +#define UINT_FAST32_TYPE "unsigned int" +#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int") + +#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int") +#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int") diff --git a/gcc/configure b/gcc/configure index c823ffe..cc542ac 100755 --- a/gcc/configure +++ b/gcc/configure @@ -24819,6 +24819,61 @@ $as_echo "#define HAVE_AS_AVR_MRMW_OPTION 1" >>confdefs.h fi + + # Check how default linker description file implements .rodata for + # avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to + # RAM so avr-gcc skips __do_copy_data for .rodata objects. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking binutils for avrxmega3 .rodata support" >&5 +$as_echo_n "checking binutils for avrxmega3 .rodata support... " >&6; } + cat > conftest.s <<EOF + .section .rodata,"a",@progbits + .global xxvaryy + ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy". + xxvaryy: + .word 1 +EOF + rm -f conftest.nm + { ac_try='$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + { ac_try='$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + { ac_try='$gcc_cv_nm conftest.elf > conftest.nm' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + if test -f conftest.nm + then + if grep ' R xxvaryy' conftest.nm > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + rm -f conftest.s conftest.o conftest.elf conftest.nm + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no: avrxmega3 .rodata located in RAM" >&5 +$as_echo "no: avrxmega3 .rodata located in RAM" >&6; } + echo "$as_me: nm output was" >&5 + cat conftest.nm >&5 + rm -f conftest.s conftest.o conftest.elf conftest.nm + avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`" + as_fn_error "support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)" "$LINENO" 5 + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: test failed" >&5 +$as_echo "test failed" >&6; } + echo "$as_me: failed program was" >&5 + cat conftest.s >&5 + rm -f conftest.s conftest.o conftest.elf + as_fn_error "see \`config.log' for details" "$LINENO" 5 + fi ;; cris-*-*) diff --git a/gcc/configure.ac b/gcc/configure.ac index acfe979..b54f797 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3816,6 +3816,42 @@ AS_HELP_STRING([--disable-fix-cortex-a53-843419], [-mrmw], [.text],, [AC_DEFINE(HAVE_AS_AVR_MRMW_OPTION, 1, [Define if your avr assembler supports -mrmw option.])]) + + # Check how default linker description file implements .rodata for + # avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to + # RAM so avr-gcc skips __do_copy_data for .rodata objects. + AC_MSG_CHECKING(binutils for avrxmega3 .rodata support) + cat > conftest.s <<EOF + .section .rodata,"a",@progbits + .global xxvaryy + ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy". + xxvaryy: + .word 1 +EOF + rm -f conftest.nm + AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o]) + AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf]) + AC_TRY_COMMAND([$gcc_cv_nm conftest.elf > conftest.nm]) + if test -f conftest.nm + then + if grep ' R xxvaryy' conftest.nm > /dev/null; then + AC_MSG_RESULT(yes) + rm -f conftest.s conftest.o conftest.elf conftest.nm + else + AC_MSG_RESULT(no: avrxmega3 .rodata located in RAM) + echo "$as_me: nm output was" >&AS_MESSAGE_LOG_FD + cat conftest.nm >&AS_MESSAGE_LOG_FD + rm -f conftest.s conftest.o conftest.elf conftest.nm + avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`" + AC_MSG_ERROR([[support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)]]) + fi + else + AC_MSG_RESULT(test failed) + echo "$as_me: failed program was" >&AS_MESSAGE_LOG_FD + cat conftest.s >&AS_MESSAGE_LOG_FD + rm -f conftest.s conftest.o conftest.elf + AC_MSG_ERROR([[see `config.log' for details]]) + fi ;; cris-*-*) diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi index deb0dd3..15fd414 100644 --- a/gcc/doc/avr-mmcu.texi +++ b/gcc/doc/avr-mmcu.texi @@ -52,6 +52,10 @@ ``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB of program memory. @*@var{mcu}@tie{}= @code{atxmega16a4}, @code{atxmega16a4u}, @code{atxmega16c4}, @code{atxmega16d4}, @code{atxmega16e5}, @code{atxmega32a4}, @code{atxmega32a4u}, @code{atxmega32c3}, @code{atxmega32c4}, @code{atxmega32d3}, @code{atxmega32d4}, @code{atxmega32e5}, @code{atxmega8e5}. +@item avrxmega3 +``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, and with program memory visible in the RAM address space. +@*@var{mcu}@tie{}= @code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny212}, @code{attiny214}, @code{attiny3214}, @code{attiny3216}, @code{attiny3217}, @code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny417}, @code{attiny814}, @code{attiny816}, @code{attiny817}. + @item avrxmega4 ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory. @*@var{mcu}@tie{}= @code{atxmega64a3}, @code{atxmega64a3u}, @code{atxmega64a4u}, @code{atxmega64b1}, @code{atxmega64b3}, @code{atxmega64c3}, @code{atxmega64d3}, @code{atxmega64d4}. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index d467a16..ef1ae73 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1312,11 +1312,24 @@ in order to put read-only data into the flash memory and access that data by means of the special instructions @code{LPM} or @code{ELPM} needed to read from flash. -Per default, any data including read-only data is located in RAM -(the generic address space) so that non-generic address spaces are -needed to locate read-only data in flash memory -@emph{and} to generate the right instructions to access this data -without using (inline) assembler code. +Devices belonging to @code{avrtiny} and @code{avrxmega3} can access +flash memory by means of @code{LD*} instructions because the flash +memory is mapped into the RAM address space. There is @emph{no need} +for language extensions like @code{__flash} or attribute +@ref{AVR Variable Attributes,,@code{progmem}}. +The default linker description files for these devices cater for that +feature and @code{.rodata} stays in flash: The compiler just generates +@code{LD*} instructions, and the linker script adds core specific +offsets to all @code{.rodata} symbols: @code{0x4000} in the case of +@code{avrtiny} and @code{0x8000} in the case of @code{avrxmega3}. +See @ref{AVR Options} for a list of respective devices. + +For devices not in @code{avrtiny} or @code{avrxmega3}, +any data including read-only data is located in RAM (the generic +address space) because flash memory is not visible in the RAM address +space. In order to locate read-only data in flash memory @emph{and} +to generate the right instructions to access this data without +using (inline) assembler code, special address spaces are needed. @table @code @item __flash @@ -1447,14 +1460,11 @@ extern const __memx char foo; const __memx void *pfoo = &foo; @end smallexample -@noindent -Such code requires at least binutils 2.23, see -@w{@uref{https://sourceware.org/PR13503,PR13503}}. - @item On the reduced Tiny devices like ATtiny40, no address spaces are supported. -Data can be put into and read from flash memory by means of -attribute @code{progmem}, see @ref{AVR Variable Attributes}. +Just use vanilla C / C++ code without overhead as outlined above. +Attribute @code{progmem} is supported but works differently, +see @ref{AVR Variable Attributes}. @end itemize @@ -5936,6 +5946,19 @@ normally resides in the data memory (RAM). See also the @ref{AVR Named Address Spaces} section for an alternate way to locate and access data in flash memory. +@item @bullet{}@tie{} AVR cores with flash memory visible in the RAM address range: +On such devices, there is no need for attribute @code{progmem} or +@ref{AVR Named Address Spaces,,@code{__flash}} qualifier at all. +Just use standard C / C++. The compiler will generate @code{LD*} +instructions. As flash memory is visible in the RAM address range, +and the default linker script does @emph{not} locate @code{.rodata} in +RAM, no special features are needed in order not to waste RAM for +read-only data or to read from flash. You might even get slightly better +performance by +avoiding @code{progmem} and @code{__flash}. This applies to devices from +families @code{avrtiny} and @code{avrxmega3}, see @ref{AVR Options} for +an overview. + @item @bullet{}@tie{}Reduced AVR Tiny cores like ATtiny40: The compiler adds @code{0x4000} to the addresses of objects and declarations in @code{progmem} and locates @@ -5957,28 +5980,7 @@ int read_var (int i) @end smallexample Please notice that on these devices, there is no need for @code{progmem} -at all. Just use an appropriate linker description file like outlined below. - -@smallexample - .text : - @{ ... - @} > text - /* Leave .rodata in flash and add an offset of 0x4000 to all - addresses so that respective objects can be accessed by - LD instructions and open coded C/C++. This means there - is no need for progmem in the source and no overhead by - read-only data in RAM. */ - .rodata ADDR(.text) + SIZEOF (.text) + 0x4000 : - @{ - *(.rodata) - *(.rodata*) - *(.gnu.linkonce.r*) - @} AT> text - /* No more need to put .rodata into .data: - Removed all .rodata entries from .data. */ - .data : - @{ ... -@end smallexample +at all. @end table diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5d41649..653bc07 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -662,7 +662,7 @@ Objective-C and Objective-C++ Dialects}. -mbranch-cost=@var{cost} @gol -mcall-prologues -mint8 -mn_flash=@var{size} -mno-interrupts @gol -mrelax -mrmw -mstrict-X -mtiny-stack -mfract-convert-truncate @gol --nodevicelib @gol +-mshort-calls -nodevicelib @gol -Waddr-space-convert -Wmisspelled-isr} @emph{Blackfin Options} @@ -15637,6 +15637,15 @@ section on @code{EIND} and linker stubs below. Assume that the device supports the Read-Modify-Write instructions @code{XCH}, @code{LAC}, @code{LAS} and @code{LAT}. +@item -mshort-calls +@opindex mshort-calls + +Assume that @code{RJMP} and @code{RCALL} can target the whole +program memory. + +This option is used internally for multilib selection. It is +not an optimization option, and you don't need to set it by hand. + @item -msp8 @opindex msp8 Treat the stack pointer register as an 8-bit register, @@ -15897,10 +15906,12 @@ for @var{mcu}=@code{avr2}, @code{avr25}, @code{avr3}, @code{avr31}, respectively and -@code{100}, @code{102}, @code{104}, +@code{100}, +@code{102}, @code{103}, @code{104}, @code{105}, @code{106}, @code{107} -for @var{mcu}=@code{avrtiny}, @code{avrxmega2}, @code{avrxmega4}, +for @var{mcu}=@code{avrtiny}, +@code{avrxmega2}, @code{avrxmega3}, @code{avrxmega4}, @code{avrxmega5}, @code{avrxmega6}, @code{avrxmega7}, respectively. If @var{mcu} specifies a device, this built-in macro is set accordingly. For example, with @option{-mmcu=atmega8} the macro is @@ -15952,7 +15963,7 @@ The device has a hardware multiplier. @item __AVR_HAVE_JMP_CALL__ The device has the @code{JMP} and @code{CALL} instructions. -This is the case for devices with at least 16@tie{}KiB of program +This is the case for devices with more than 8@tie{}KiB of program memory. @item __AVR_HAVE_EIJMP_EICALL__ @@ -16009,6 +16020,21 @@ or @code{STS}. This offset depends on the device architecture and has to be subtracted from the RAM address in order to get the respective I/O@tie{}address. +@item __AVR_SHORT_CALLS__ +The @option{-mshort-calls} command line option is set. + +@item __AVR_PM_BASE_ADDRESS__=@var{addr} +Some devices support reading from flash memory by means of @code{LD*} +instructions. The flash memory is seen in the data address space +at an offset of @code{__AVR_PM_BASE_ADDRESS__}. If this macro +is not defined, this feature is not available. If defined, +the address space is linear and there is no need to put +@code{.rodata} into RAM. This is handled by the default linker +description file, and is currently available for +@code{avrtiny} and @code{avrxmega3}. Even more convenient, +there is no need to use address spaces like @code{__flash} or +features like attribute @code{progmem} and @code{pgm_read_*}. + @item __WITH_AVRLIBC__ The compiler is configured to be used together with AVR-Libc. See the @option{--with-avrlibc} configure option. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index f3975c7..74bbdb0 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -4745,6 +4745,40 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh, *pin_p = in_p, *plow = low, *phigh = high; return exp; } + +/* Returns TRUE if [LOW, HIGH] range check can be optimized to + a bitwise check i.e. when + LOW == 0xXX...X00...0 + HIGH == 0xXX...X11...1 + Return corresponding mask in MASK and stem in VALUE. */ + +static bool +maskable_range_p (const_tree low, const_tree high, tree type, tree *mask, + tree *value) +{ + if (TREE_CODE (low) != INTEGER_CST + || TREE_CODE (high) != INTEGER_CST) + return false; + + unsigned prec = TYPE_PRECISION (type); + wide_int lo = wi::to_wide (low, prec); + wide_int hi = wi::to_wide (high, prec); + + wide_int end_mask = lo ^ hi; + if ((end_mask & (end_mask + 1)) != 0 + || (lo & end_mask) != 0) + return false; + + wide_int stem_mask = ~end_mask; + wide_int stem = lo & stem_mask; + if (stem != (hi & stem_mask)) + return false; + + *mask = wide_int_to_tree (type, stem_mask); + *value = wide_int_to_tree (type, stem); + + return true; +} /* Given a range, LOW, HIGH, and IN_P, an expression, EXP, and a result type, TYPE, return an expression to test if EXP is in (or out of, depending @@ -4754,7 +4788,7 @@ tree build_range_check (location_t loc, tree type, tree exp, int in_p, tree low, tree high) { - tree etype = TREE_TYPE (exp), value; + tree etype = TREE_TYPE (exp), mask, value; /* Disable this optimization for function pointer expressions on targets that require function pointer canonicalization. */ @@ -4787,6 +4821,13 @@ build_range_check (location_t loc, tree type, tree exp, int in_p, return fold_build2_loc (loc, EQ_EXPR, type, exp, fold_convert_loc (loc, etype, low)); + if (TREE_CODE (exp) == BIT_AND_EXPR + && maskable_range_p (low, high, etype, &mask, &value)) + return fold_build2_loc (loc, EQ_EXPR, type, + fold_build2_loc (loc, BIT_AND_EXPR, etype, + exp, mask), + value); + if (integer_zerop (low)) { if (! TYPE_UNSIGNED (etype)) @@ -6241,11 +6282,6 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type, if (TYPE_UNSIGNED (ctype) && ctype != type) break; - /* If we were able to eliminate our operation from the first side, - apply our operation to the second side and reform the PLUS. */ - if (t1 != 0 && (TREE_CODE (t1) != code || code == MULT_EXPR)) - return fold_build2 (tcode, ctype, fold_convert (ctype, t1), op1); - /* The last case is if we are a multiply. In that case, we can apply the distributive law to commute the multiply and addition if the multiplication of the constants doesn't overflow @@ -8908,7 +8944,7 @@ fold_addr_of_array_ref_difference (location_t loc, tree type, tree op0 = fold_convert_loc (loc, type, TREE_OPERAND (aref0, 1)); tree op1 = fold_convert_loc (loc, type, TREE_OPERAND (aref1, 1)); tree esz = fold_convert_loc (loc, type, array_ref_element_size (aref0)); - tree diff = build2 (MINUS_EXPR, type, op0, op1); + tree diff = fold_build2_loc (loc, MINUS_EXPR, type, op0, op1); return fold_build2_loc (loc, PLUS_EXPR, type, base_offset, fold_build2_loc (loc, MULT_EXPR, type, diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 5ff63a1..447921be 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -80,17 +80,22 @@ debug_gimple_stmt (gimple *gs) by xstrdup_for_dump. */ static const char * -dump_probability (int value) +dump_probability (int frequency, profile_count &count) { float minimum = 0.01f; - gcc_assert (0 <= value && value <= REG_BR_PROB_BASE); - float fvalue = value * 100.0f / REG_BR_PROB_BASE; - if (fvalue < minimum && value > 0) + gcc_assert (0 <= frequency && frequency <= REG_BR_PROB_BASE); + float fvalue = frequency * 100.0f / REG_BR_PROB_BASE; + if (fvalue < minimum && frequency > 0) return "[0.01%]"; char *buf; - asprintf (&buf, "[%.2f%%]", fvalue); + if (count.initialized_p ()) + asprintf (&buf, "[%.2f%%] [count: %" PRId64 "]", fvalue, + count.to_gcov_type ()); + else + asprintf (&buf, "[%.2f%%] [count: INV]", fvalue); + const char *ret = xstrdup_for_dump (buf); free (buf); @@ -102,7 +107,7 @@ dump_probability (int value) static void dump_edge_probability (pretty_printer *buffer, edge e) { - pp_scalar (buffer, " %s", dump_probability (e->probability)); + pp_scalar (buffer, " %s", dump_probability (e->probability, e->count)); } /* Print GIMPLE statement G to FILE using SPC indentation spaces and @@ -1085,7 +1090,7 @@ dump_gimple_label (pretty_printer *buffer, glabel *gs, int spc, dump_generic_node (buffer, label, spc, flags, false); basic_block bb = gimple_bb (gs); if (bb && !(flags & TDF_GIMPLE)) - pp_scalar (buffer, " %s", dump_probability (bb->frequency)); + pp_scalar (buffer, " %s", dump_probability (bb->frequency, bb->count)); pp_colon (buffer); } if (flags & TDF_GIMPLE) @@ -2665,7 +2670,8 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent, fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index); else fprintf (outf, "%*s<bb %d> %s:\n", - indent, "", bb->index, dump_probability (bb->frequency)); + indent, "", bb->index, dump_probability (bb->frequency, + bb->count)); } } } diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 1bfac59..78bd057 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -d4875b19266d5f726e0e32843b903075f5c50b4c +c4ecdd3edb9febe72b5527481ae3d7310105ca67 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index d6d27ee..5eec731 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3410,11 +3410,13 @@ Type_conversion_expression::do_get_backend(Translate_context* context) Gogo* gogo = context->gogo(); Btype* btype = type->get_backend(gogo); - Bexpression* bexpr = this->expr_->get_backend(context); Location loc = this->location(); if (Type::are_identical(type, expr_type, false, NULL)) - return gogo->backend()->convert_expression(btype, bexpr, loc); + { + Bexpression* bexpr = this->expr_->get_backend(context); + return gogo->backend()->convert_expression(btype, bexpr, loc); + } else if (type->interface_type() != NULL || expr_type->interface_type() != NULL) { @@ -3483,6 +3485,7 @@ Type_conversion_expression::do_get_backend(Translate_context* context) else if (type->is_numeric_type()) { go_assert(Type::are_convertible(type, expr_type, NULL)); + Bexpression* bexpr = this->expr_->get_backend(context); return gogo->backend()->convert_expression(btype, bexpr, loc); } else if ((type->is_unsafe_pointer_type() @@ -3493,7 +3496,10 @@ Type_conversion_expression::do_get_backend(Translate_context* context) || (this->may_convert_function_types_ && type->function_type() != NULL && expr_type->function_type() != NULL)) - return gogo->backend()->convert_expression(btype, bexpr, loc); + { + Bexpression* bexpr = this->expr_->get_backend(context); + return gogo->backend()->convert_expression(btype, bexpr, loc); + } else { Expression* conversion = diff --git a/gcc/match.pd b/gcc/match.pd index 54a8e04..244e9eb 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2741,6 +2741,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0))) { constant_boolean_node (false, type); }))) +/* A & (2**N - 1) <= 2**K - 1 -> A & (2**N - 2**K) == 0 + A & (2**N - 1) > 2**K - 1 -> A & (2**N - 2**K) != 0 + + Note that comparisons + A & (2**N - 1) < 2**K -> A & (2**N - 2**K) == 0 + A & (2**N - 1) >= 2**K -> A & (2**N - 2**K) != 0 + will be canonicalized to above so there's no need to + consider them here. + */ + +(for cmp (le gt) + eqcmp (eq ne) + (simplify + (cmp (bit_and@0 @1 INTEGER_CST@2) INTEGER_CST@3) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))) + (with + { + tree ty = TREE_TYPE (@0); + unsigned prec = TYPE_PRECISION (ty); + wide_int mask = wi::to_wide (@2, prec); + wide_int rhs = wi::to_wide (@3, prec); + signop sgn = TYPE_SIGN (ty); + } + (if ((mask & (mask + 1)) == 0 && wi::gt_p (rhs, 0, sgn) + && (rhs & (rhs + 1)) == 0 && wi::ge_p (mask, rhs, sgn)) + (eqcmp (bit_and @1 { wide_int_to_tree (ty, mask - rhs); }) + { build_zero_cst (ty); })))))) + /* -A CMP -B -> B CMP A. */ (for cmp (tcc_comparison) scmp (swapped_tcc_comparison) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 531c787..d9a9fb2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,68 @@ +2017-06-13 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/80803 + PR tree-optimization/81063 + gcc.dg/tree-ssa/pr80803.c: New test. + gcc.dg/tree-ssa/pr81063.c: Likewise. + +2017-06-12 Yury Gribov <tetra2005@gmail.com> + + * c-c++-common/fold-masked-cmp-3.c: New test. + +2017-06-13 Yury Gribov <tetra2005@gmail.com> + + PR tree-optimization/67328 + * c-c++-common/fold-masked-cmp-1.c: New test. + * c-c++-common/fold-masked-cmp-2.c: Likewise. + * gcc.dg/pr46309.c: Fix pattern. + * gcc.dg/pr46309-2.c: Likewise. + +2017-06-13 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/arm/sdiv_costs_1.c: + Require arm_arch_v8a_ok and add march option. + +2017-06-13 Martin Liska <mliska@suse.cz> + + * gcc.dg/tree-ssa/builtin-sprintf-2.c: Adjust scanned pattern. + * gcc.dg/tree-ssa/dump-2.c: Likewise. + * gcc.dg/tree-ssa/vrp101.c: Likewise. + +2017-06-13 Richard Biener <rguenther@suse.de> + + PR middle-end/81065 + * c-c++-common/ubsan/pr81065.c: New testcase. + +2017-06-12 Ian Lance Taylor <iant@golang.org> + + * gcc.dg/tree-prof/split-1.c: Require split_stack, don't require + freorder. Update comment to explain test. + +2017-06-12 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/inline-lrint_1.c: Broaden regexp. + * gcc.target/aarch64/inline-lrint_2.c: Likewise. + * gcc.target/aarch64/no-inline-lrint_1.c: Likewise. + * gcc.target/aarch64/no-inline-lrint_2.c: Likewise. + +2017-06-12 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/arm/sdiv_costs_1.c: Require arm_v8_vfp_ok. + +2017-06-12 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/arm/sdiv_costs_1.c: Disable on softfloat. + +2017-06-12 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/81003 + * gcc.c-torture/compile/pr81003.c: New test. + +2017-06-12 Richard Biener <rguenther@suse.de> + + PR tree-optimization/81053 + * gcc.dg/torture/pr81053.c: New testcase. + 2017-06-10 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/80988 diff --git a/gcc/testsuite/c-c++-common/fold-masked-cmp-1.c b/gcc/testsuite/c-c++-common/fold-masked-cmp-1.c new file mode 100644 index 0000000..a0e9083 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fold-masked-cmp-1.c @@ -0,0 +1,41 @@ +/* Based on PR 67328 */ + +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O2" } */ + +enum output_type +{ + type_pde, + type_pie, + type_relocatable, + type_dll, +}; + +struct bfd_link_info +{ + enum output_type type : 2; + unsigned int pad : 30; +}; + +#define bfd_link_pde(info) ((info)->type == type_pde) +#define bfd_link_dll(info) ((info)->type == type_dll) +#define bfd_link_relocatable(info) ((info)->type == type_relocatable) +#define bfd_link_pie(info) ((info)->type == type_pie) +#define bfd_link_executable(info) (bfd_link_pde (info) || bfd_link_pie (info)) +#define bfd_link_pic(info) (bfd_link_dll (info) || bfd_link_pie (info)) + +int result; + +void test_pic (struct bfd_link_info *info) +{ + if (bfd_link_pic (info)) + result++; +} + +int test_exe (struct bfd_link_info *info) +{ + if (bfd_link_executable (info)) + result++; +} + +/* { dg-final { scan-assembler-times "testn?b" 2 } } */ diff --git a/gcc/testsuite/c-c++-common/fold-masked-cmp-2.c b/gcc/testsuite/c-c++-common/fold-masked-cmp-2.c new file mode 100644 index 0000000..13d068a --- /dev/null +++ b/gcc/testsuite/c-c++-common/fold-masked-cmp-2.c @@ -0,0 +1,42 @@ +/* Based on PR 67328 */ + +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O2" } */ + +enum output_type +{ + type_pde, + type_relocatable, + type_pie, + type_dll, +}; + +struct bfd_link_info +{ + enum output_type type : 2; + unsigned int pad : 30; +}; + +#define bfd_link_pde(info) ((info)->type == type_pde) +#define bfd_link_dll(info) ((info)->type == type_dll) +#define bfd_link_relocatable(info) ((info)->type == type_relocatable) +#define bfd_link_pie(info) ((info)->type == type_pie) +#define bfd_link_executable(info) (bfd_link_pde (info) || bfd_link_pie (info)) +#define bfd_link_pic(info) (bfd_link_dll (info) || bfd_link_pie (info)) + +int result; + +void test_pic (struct bfd_link_info *info) +{ + if (bfd_link_pic (info)) + result++; +} + +int test_exe (struct bfd_link_info *info) +{ + if (bfd_link_executable (info)) + result++; +} + +/* { dg-final { scan-assembler-times "testn?b" 2 } } */ + diff --git a/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c b/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c new file mode 100644 index 0000000..98900ec3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-fdump-tree-original" } */ + +void foo (int *p, int x) +{ + if ((x & 0xff) <= 7) + *p = 0; +} + +void bar (int *p, int x) +{ + if ((x & 0xff) < 8) + *p = 0; +} + +/* { dg-final { scan-tree-dump-times "(x & .*) == 0" 2 "original" } } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/pr81065.c b/gcc/testsuite/c-c++-common/ubsan/pr81065.c new file mode 100644 index 0000000..1b34227 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr81065.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */ + +unsigned char x = 154; +int foo() { + // 8575 * (254408 - 9057) = 8575 * 245351 = 2103884825 = 0x7d66bc19 + return 8575 * (1652 * x - 9057); +} + +int main() { + foo(); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr81003.c b/gcc/testsuite/gcc.c-torture/compile/pr81003.c new file mode 100644 index 0000000..26117b6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr81003.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/81003 */ + +unsigned int a, b; + +void +foo (void) +{ + for (b = 0; b < 13; b += 2) + a &= !!b; +} diff --git a/gcc/testsuite/gcc.dg/pr46309-2.c b/gcc/testsuite/gcc.dg/pr46309-2.c index 39b9b83..f56df42 100644 --- a/gcc/testsuite/gcc.dg/pr46309-2.c +++ b/gcc/testsuite/gcc.dg/pr46309-2.c @@ -142,4 +142,4 @@ f10 (int a) /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.0, 31. and -.64, 95.\[\n\r\]* into" 1 "reassoc1" } } */ /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.128, 159. and -.192, 223.\[\n\r\]* into" 1 "reassoc1" } } */ /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.1, 1. and -.2, 2. and -.3, 3. and -.4, 4. and -.5, 5. and -.6, 6. and -.7, 7. and -.8, 8.\[\n\r\]* into" 7 "reassoc1" } } */ -/* { dg-final { scan-tree-dump-times "Optimizing range tests \[^\r\n\]*_\[0-9\]* -.0, 31. and -.128, 159.\[\n\r\]* into" 1 "reassoc2" } } */ +/* { dg-final { scan-tree-dump-times "Optimizing range tests \[^\r\n\]*_\[0-9\]* -.0, 0. and -.128, 128.\[\n\r\]* into" 1 "reassoc2" } } */ diff --git a/gcc/testsuite/gcc.dg/pr46309.c b/gcc/testsuite/gcc.dg/pr46309.c index f362ac3..68229cf 100644 --- a/gcc/testsuite/gcc.dg/pr46309.c +++ b/gcc/testsuite/gcc.dg/pr46309.c @@ -65,4 +65,4 @@ f6 (unsigned int a) /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.1, 1. and -.2, 2.\[\n\r\]* into" 1 "reassoc1" } } */ /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.0, 31. and -.64, 95.\[\n\r\]* into" 2 "reassoc1" } } */ /* { dg-final { scan-tree-dump-times "Optimizing range tests a_\[0-9\]*.D. -.128, 159. and -.192, 223.\[\n\r\]* into" 1 "reassoc1" } } */ -/* { dg-final { scan-tree-dump-times "Optimizing range tests \[^\r\n\]*_\[0-9\]* -.0, 31. and -.128, 159.\[\n\r\]* into" 1 "reassoc2" } } */ +/* { dg-final { scan-tree-dump-times "Optimizing range tests \[^\r\n\]*_\[0-9\]* -.0, 0. and -.128, 128.\[\n\r\]* into" 1 "reassoc2" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr81053.c b/gcc/testsuite/gcc.dg/torture/pr81053.c new file mode 100644 index 0000000..98ab95d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr81053.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +int a, b[2], c, d; + +void fn1 () +{ + for (; d < 2; d++) + { + b[d] = a; + a = c; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-prof/split-1.c b/gcc/testsuite/gcc.dg/tree-prof/split-1.c index a42fccf..6986f7a 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/split-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/split-1.c @@ -1,6 +1,6 @@ -/* Test case that we don't get a link-time error when using - -fsplit-stack with -freorder-blocks-and-partition. */ -/* { dg-require-effective-target freorder } */ +/* Test that we don't get a link-time error when using -fsplit-stack + due to implicit enabling of -freorder-blocks-and-partition. */ +/* { dg-require-effective-target split_stack } */ /* { dg-options "-O2 -fsplit-stack" } */ extern unsigned int sleep (unsigned int); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c index 8a13f33..e15d88b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-sprintf-2.c @@ -290,7 +290,7 @@ RNG (0, 6, 8, "%s%ls", "1", L"2"); /* Only conditional calls to must_not_eliminate must be made (with any probability): - { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *must_not_eliminate" 127 "optimized" { target { ilp32 || lp64 } } } } - { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]:\n *must_not_eliminate" 96 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } } + { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]\\ \\\[count:\\[^:\\]*\\\]:\n *must_not_eliminate" 127 "optimized" { target { ilp32 || lp64 } } } } + { dg-final { scan-tree-dump-times "> \\\[\[0-9.\]+%\\\]\\ \\\[count:\\[^:\\]*\\\]:\n *must_not_eliminate" 96 "optimized" { target { { ! ilp32 } && { ! lp64 } } } } } No unconditional calls to abort should be made: { dg-final { scan-tree-dump-not ";\n *must_not_eliminate" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c index 8a63af4..6ae2ef5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-2.c @@ -6,4 +6,4 @@ int f(void) return 0; } -/* { dg-final { scan-tree-dump "<bb \[0-9\]> \\\[100\\\.00%\\\]:" "optimized" } } */ +/* { dg-final { scan-tree-dump "<bb \[0-9\]> \\\[100\\\.00%\\\] \\\[count: INV\\\]:" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c b/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c new file mode 100644 index 0000000..66834fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr80803.c @@ -0,0 +1,72 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +struct S0 +{ + unsigned a : 15; + int b; + int c; +}; + +struct S1 +{ + struct S0 s0; + int e; +}; + +struct Z +{ + char c; + int z; +} __attribute__((packed)); + +union U +{ + struct S1 s1; + struct Z z; +}; + + +int __attribute__((noinline, noclone)) +return_zero (void) +{ + return 0; +} + +volatile union U gu; +struct S0 gs; + +int __attribute__((noinline, noclone)) +check_outcome () +{ + if (gs.a != 6 + || gs.b != 80000) + __builtin_abort (); +} + +int +main (int argc, char *argv[]) +{ + union U u; + struct S1 m,n; + struct S0 l; + + if (return_zero ()) + u.z.z = 20000; + else + { + u.s1.s0.a = 6; + u.s1.s0.b = 80000; + u.s1.e = 2; + + n = u.s1; + m = n; + m.s0.c = 0; + l = m.s0; + gs = l; + } + + gu = u; + check_outcome (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c b/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c new file mode 100644 index 0000000..399e2d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr81063.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +struct A +{ + int b; + int c:2; +}; + +struct B +{ + int e; + struct A f; +} g = {0, {0, 1}}, j; + +struct A *h = &g.f; + +int main () +{ + struct A k; + struct B l = j, i = l; + if (!i.f.b) + k = i.f; + *h = k; + if (g.f.c != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c index bf4109f..e7cad28 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp101.c @@ -10,4 +10,4 @@ int main () return 0; } -/* { dg-final { scan-tree-dump "<bb 2> \\\[\[0-9.\]+%\\\]:\[\n\r \]*return 0;" "optimized" } } */ +/* { dg-final { scan-tree-dump "<bb 2> \\\[\[0-9.\]+%\\\] \\\[count: \\[^:\\]*\\\]:\[\n\r \]*return 0;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c index 876cecd..478875f 100644 --- a/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c +++ b/gcc/testsuite/gcc.target/aarch64/inline-lrint_1.c @@ -13,8 +13,6 @@ TEST (fif, float , int, ) TEST (dlld, double, long long, l) TEST (fllf, float , long long, l) -/* { dg-final { scan-assembler-times "frintx\td\[0-9\]+, d\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "frintx\ts\[0-9\]+, s\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, d\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, s\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ +/* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ /* { dg-final { scan-assembler-not "bl" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/inline-lrint_2.c b/gcc/testsuite/gcc.target/aarch64/inline-lrint_2.c index baa5aee..6080e18 100644 --- a/gcc/testsuite/gcc.target/aarch64/inline-lrint_2.c +++ b/gcc/testsuite/gcc.target/aarch64/inline-lrint_2.c @@ -13,10 +13,6 @@ TEST (fif, float , int, ) TEST (dlld, double, long long, l) TEST (fllf, float , long long, l) -/* { dg-final { scan-assembler-times "frintx\td\[0-9\]+, d\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "frintx\ts\[0-9\]+, s\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, d\[0-9\]+" 1 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tx\[0-9\]+, s\[0-9\]+" 1 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tw\[0-9\]+, d\[0-9\]+" 2 } } */ -/* { dg-final { scan-assembler-times "fcvtzs\tw\[0-9\]+, s\[0-9\]+" 2 } } */ +/* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ +/* { dg-final { scan-assembler-times "fcvtzs\t\[w,x\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ /* { dg-final { scan-assembler-not "bl" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c index fb7f065..d5e9200 100644 --- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c +++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c @@ -13,8 +13,7 @@ TEST (fif, float , int, ) TEST (dlld, double, long long, l) TEST (fllf, float , long long, l) -/* { dg-final { scan-assembler-times "frintx\td\[0-9\]+, d\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "frintx\ts\[0-9\]+, s\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ /* { dg-final { scan-assembler-times "bl\tlrint" 4 } } */ /* { dg-final { scan-assembler-times "bl\tllrint" 2 } } */ /* { dg-final { scan-assembler-not "fcvtzs" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_2.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_2.c index c99843c..05c0a2a 100644 --- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_2.c +++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_2.c @@ -13,8 +13,7 @@ TEST (fif, float , int, ) TEST (dlld, double, long long, l) TEST (fllf, float , long long, l) -/* { dg-final { scan-assembler-times "frintx\td\[0-9\]+, d\[0-9\]+" 3 } } */ -/* { dg-final { scan-assembler-times "frintx\ts\[0-9\]+, s\[0-9\]+" 3 } } */ +/* { dg-final { scan-assembler-times "frintx\t\[d,s\]\[0-9\]+, \[d,s\]\[0-9\]+" 6 } } */ /* { dg-final { scan-assembler-times "bl\tlrint" 4 } } */ /* { dg-final { scan-assembler-times "bl\tllrint" 2 } } */ /* { dg-final { scan-assembler-not "fcvtzs" } } */ diff --git a/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c b/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c index 76086ab..9d094ac 100644 --- a/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c +++ b/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O3 -march=armv8-a" } */ +/* { dg-require-effective-target arm_arch_v8a_ok } */ /* Both sdiv and udiv can be used here, so prefer udiv. */ int f1 (unsigned char *p) diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index f5c0668..2ae4b69 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -429,6 +429,10 @@ gimple_gen_ic_func_profiler (void) basic_block cond_bb = split_edge (single_succ_edge (entry)); basic_block update_bb = split_edge (single_succ_edge (cond_bb)); + /* We need to do an extra split in order to not create an input + for a possible PHI node. */ + split_edge (single_succ_edge (update_bb)); + edge true_edge = single_succ_edge (cond_bb); true_edge->flags = EDGE_TRUE_VALUE; @@ -487,6 +491,10 @@ gimple_gen_time_profiler (unsigned tag, unsigned base) basic_block cond_bb = split_edge (single_succ_edge (entry)); basic_block update_bb = split_edge (single_succ_edge (cond_bb)); + /* We need to do an extra split in order to not create an input + for a possible PHI node. */ + split_edge (single_succ_edge (update_bb)); + edge true_edge = single_succ_edge (cond_bb); true_edge->flags = EDGE_TRUE_VALUE; true_edge->probability = PROB_UNLIKELY; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index f25818f..c9865c6 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -470,7 +470,7 @@ dump_access_tree_1 (FILE *f, struct access *access, int level) int i; for (i = 0; i < level; i++) - fputs ("* ", dump_file); + fputs ("* ", f); dump_access (f, access, true); @@ -627,7 +627,7 @@ relink_to_new_repr (struct access *new_racc, struct access *old_racc) static void add_access_to_work_queue (struct access *access) { - if (!access->grp_queued) + if (access->first_link && !access->grp_queued) { gcc_assert (!access->next_queued); access->next_queued = work_queue_head; @@ -2112,8 +2112,7 @@ sort_and_splice_var_accesses (tree var) access->grp_total_scalarization = total_scalarization; access->grp_partial_lhs = grp_partial_lhs; access->grp_unscalarizable_region = unscalarizable_region; - if (access->first_link) - add_access_to_work_queue (access); + add_access_to_work_queue (access); *prev_acc_ptr = access; prev_acc_ptr = &access->next_grp; @@ -2559,9 +2558,28 @@ create_artificial_child_access (struct access *parent, struct access *model, } -/* Propagate all subaccesses of RACC across an assignment link to LACC. Return - true if any new subaccess was created. Additionally, if RACC is a scalar - access but LACC is not, change the type of the latter, if possible. */ +/* Beginning with ACCESS, traverse its whole access subtree and mark all + sub-trees as written to. If any of them has not been marked so previously + and has assignment links leading from it, re-enqueue it. */ + +static void +subtree_mark_written_and_enqueue (struct access *access) +{ + if (access->grp_write) + return; + access->grp_write = true; + add_access_to_work_queue (access); + + struct access *child; + for (child = access->first_child; child; child = child->next_sibling) + subtree_mark_written_and_enqueue (child); +} + +/* Propagate subaccesses and grp_write flags of RACC across an assignment link + to LACC. Enqueue sub-accesses as necessary so that the write flag is + propagated transitively. Return true if anything changed. Additionally, if + RACC is a scalar access but LACC is not, change the type of the latter, if + possible. */ static bool propagate_subaccesses_across_link (struct access *lacc, struct access *racc) @@ -2577,7 +2595,7 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) gcc_checking_assert (!comes_initialized_p (racc->base)); if (racc->grp_write) { - lacc->grp_write = true; + subtree_mark_written_and_enqueue (lacc); ret = true; } } @@ -2586,13 +2604,21 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) || lacc->grp_unscalarizable_region || racc->grp_unscalarizable_region) { - ret |= !lacc->grp_write; - lacc->grp_write = true; + if (!lacc->grp_write) + { + ret = true; + subtree_mark_written_and_enqueue (lacc); + } return ret; } if (is_gimple_reg_type (racc->type)) { + if (!lacc->grp_write) + { + ret = true; + subtree_mark_written_and_enqueue (lacc); + } if (!lacc->first_child && !racc->first_child) { tree t = lacc->base; @@ -2617,21 +2643,15 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) struct access *new_acc = NULL; HOST_WIDE_INT norm_offset = rchild->offset + norm_delta; - if (rchild->grp_unscalarizable_region) - { - lacc->grp_write = true; - continue; - } - if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size, &new_acc)) { if (new_acc) { - if (!new_acc->grp_write - && (lacc->grp_write || rchild->grp_write)) + if (!new_acc->grp_write && rchild->grp_write) { - new_acc ->grp_write = true; + gcc_assert (!lacc->grp_write); + subtree_mark_written_and_enqueue (new_acc); ret = true; } @@ -2641,7 +2661,23 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) ret |= propagate_subaccesses_across_link (new_acc, rchild); } else - lacc->grp_write = true; + { + if (rchild->grp_write && !lacc->grp_write) + { + ret = true; + subtree_mark_written_and_enqueue (lacc); + } + } + continue; + } + + if (rchild->grp_unscalarizable_region) + { + if (rchild->grp_write && !lacc->grp_write) + { + ret = true; + subtree_mark_written_and_enqueue (lacc); + } continue; } @@ -2649,37 +2685,17 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) new_acc = create_artificial_child_access (lacc, rchild, norm_offset, lacc->grp_write || rchild->grp_write); - if (new_acc) - { - ret = true; - if (racc->first_child) - propagate_subaccesses_across_link (new_acc, rchild); - } + gcc_checking_assert (new_acc); + if (racc->first_child) + propagate_subaccesses_across_link (new_acc, rchild); + + add_access_to_work_queue (lacc); + ret = true; } return ret; } -/* Beginning with ACCESS, traverse its whole access subtree and mark all - sub-trees as written to. If any of them has not been marked so previously - and has assignment links leading from it, re-enqueue it. */ - -static void -subtree_mark_written_and_enqueue (struct access *access) -{ - if (access->grp_write) - return; - access->grp_write = true; - if (access->first_link) - add_access_to_work_queue (access); - - struct access *child; - for (child = access->first_child; child; child = child->next_sibling) - subtree_mark_written_and_enqueue (child); -} - - - /* Propagate all subaccesses across assignment links. */ static void @@ -2715,11 +2731,7 @@ propagate_all_subaccesses (void) if (reque_parents) do { - if (lacc->first_link) - { - add_access_to_work_queue (lacc); - break; - } + add_access_to_work_queue (lacc); lacc = lacc->parent; } while (lacc); diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 6831f44..35eb72c 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2282,6 +2282,26 @@ range_entry_cmp (const void *a, const void *b) } } +/* Helper function for update_range_test. Force EXPR into an SSA_NAME, + insert needed statements BEFORE or after GSI. */ + +static tree +force_into_ssa_name (gimple_stmt_iterator *gsi, tree expr, bool before) +{ + enum gsi_iterator_update m = before ? GSI_SAME_STMT : GSI_CONTINUE_LINKING; + tree ret = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE, before, m); + if (TREE_CODE (ret) != SSA_NAME) + { + gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (ret)), ret); + if (before) + gsi_insert_before (gsi, g, GSI_SAME_STMT); + else + gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING); + ret = gimple_assign_lhs (g); + } + return ret; +} + /* Helper routine of optimize_range_test. [EXP, IN_P, LOW, HIGH, STRICT_OVERFLOW_P] is a merged range for RANGE and OTHERRANGE through OTHERRANGE + COUNT - 1 ranges, @@ -2393,15 +2413,13 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, else if (op != range->exp) { gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); - tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true, - GSI_SAME_STMT); + tem = force_into_ssa_name (&gsi, tem, true); gsi_prev (&gsi); } else if (gimple_code (stmt) != GIMPLE_PHI) { gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); - tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, false, - GSI_CONTINUE_LINKING); + tem = force_into_ssa_name (&gsi, tem, false); } else { @@ -2419,8 +2437,7 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, } } gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); - tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true, - GSI_SAME_STMT); + tem = force_into_ssa_name (&gsi, tem, true); if (gsi_end_p (gsi)) gsi = gsi_last_bb (gimple_bb (stmt)); else diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 64cf05d..b8b49c9 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2790,15 +2790,17 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi, } def_stmt = SSA_NAME_DEF_STMT (loop_arg); - if (gimple_nop_p (def_stmt)) + if (is_gimple_assign (def_stmt)) { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "reduction: no def_stmt\n"); - return NULL; + name = gimple_assign_lhs (def_stmt); + phi_def = false; } - - if (!is_gimple_assign (def_stmt) && gimple_code (def_stmt) != GIMPLE_PHI) + else if (gimple_code (def_stmt) == GIMPLE_PHI) + { + name = PHI_RESULT (def_stmt); + phi_def = true; + } + else { if (dump_enabled_p ()) { @@ -2809,37 +2811,27 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi, return NULL; } - if (is_gimple_assign (def_stmt)) - { - name = gimple_assign_lhs (def_stmt); - phi_def = false; - } - else - { - name = PHI_RESULT (def_stmt); - phi_def = true; - } - nloop_uses = 0; auto_vec<gphi *, 3> lcphis; - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name) - { - gimple *use_stmt = USE_STMT (use_p); - if (is_gimple_debug (use_stmt)) - continue; - if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))) - nloop_uses++; - else - /* We can have more than one loop-closed PHI. */ - lcphis.safe_push (as_a <gphi *> (use_stmt)); - if (nloop_uses > 1) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "reduction used in loop.\n"); - return NULL; - } - } + if (flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))) + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name) + { + gimple *use_stmt = USE_STMT (use_p); + if (is_gimple_debug (use_stmt)) + continue; + if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt))) + nloop_uses++; + else + /* We can have more than one loop-closed PHI. */ + lcphis.safe_push (as_a <gphi *> (use_stmt)); + if (nloop_uses > 1) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "reduction used in loop.\n"); + return NULL; + } + } /* If DEF_STMT is a phi node itself, we expect it to have a single argument defined in the inner loop. */ @@ -3698,16 +3690,15 @@ get_reduction_op (gimple *stmt, int reduc_index) generated within the strip-mine loop, the initial definition before the loop, and the epilogue code that must be generated. */ -static bool +static void vect_model_reduction_cost (stmt_vec_info stmt_info, enum tree_code reduc_code, - int ncopies, int reduc_index) + int ncopies) { int prologue_cost = 0, epilogue_cost = 0; enum tree_code code; optab optab; tree vectype; - gimple *stmt, *orig_stmt; - tree reduction_op; + gimple *orig_stmt; machine_mode mode; loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); struct loop *loop = NULL; @@ -3728,24 +3719,8 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, enum tree_code reduc_code, /* Cost of reduction op inside loop. */ unsigned inside_cost = add_stmt_cost (target_cost_data, ncopies, vector_stmt, stmt_info, 0, vect_body); - stmt = STMT_VINFO_STMT (stmt_info); - - reduction_op = get_reduction_op (stmt, reduc_index); - - vectype = get_vectype_for_scalar_type (TREE_TYPE (reduction_op)); - if (!vectype) - { - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "unsupported data-type "); - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, - TREE_TYPE (reduction_op)); - dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); - } - return false; - } + vectype = STMT_VINFO_VECTYPE (stmt_info); mode = TYPE_MODE (vectype); orig_stmt = STMT_VINFO_RELATED_STMT (stmt_info); @@ -3837,8 +3812,6 @@ vect_model_reduction_cost (stmt_vec_info stmt_info, enum tree_code reduc_code, "vect_model_reduction_cost: inside_cost = %d, " "prologue_cost = %d, epilogue_cost = %d .\n", inside_cost, prologue_cost, epilogue_cost); - - return true; } @@ -5296,20 +5269,6 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi, /* Flatten RHS. */ switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))) { - case GIMPLE_SINGLE_RHS: - op_type = TREE_OPERAND_LENGTH (gimple_assign_rhs1 (stmt)); - if (op_type == ternary_op) - { - tree rhs = gimple_assign_rhs1 (stmt); - ops[0] = TREE_OPERAND (rhs, 0); - ops[1] = TREE_OPERAND (rhs, 1); - ops[2] = TREE_OPERAND (rhs, 2); - code = TREE_CODE (rhs); - } - else - return false; - break; - case GIMPLE_BINARY_RHS: code = gimple_assign_rhs_code (stmt); op_type = TREE_CODE_LENGTH (code); @@ -5789,10 +5748,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi, if (!vec_stmt) /* transformation not required. */ { - if (first_p - && !vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies, - reduc_index)) - return false; + if (first_p) + vect_model_reduction_cost (stmt_info, epilog_reduc_code, ncopies); STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type; return true; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 716a7c2..a7424a3 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -5628,6 +5628,82 @@ register_edge_assert_for_1 (tree op, enum tree_code code, } } +/* Check if comparison + NAME COND_OP INTEGER_CST + has a form of + (X & 11...100..0) COND_OP XX...X00...0 + Such comparison can yield assertions like + X >= XX...X00...0 + X <= XX...X11...1 + in case of COND_OP being NE_EXPR or + X < XX...X00...0 + X > XX...X11...1 + in case of EQ_EXPR. */ + +static bool +is_masked_range_test (tree name, tree valt, enum tree_code cond_code, + tree *new_name, tree *low, enum tree_code *low_code, + tree *high, enum tree_code *high_code) +{ + gimple *def_stmt = SSA_NAME_DEF_STMT (name); + + if (!is_gimple_assign (def_stmt) + || gimple_assign_rhs_code (def_stmt) != BIT_AND_EXPR) + return false; + + tree maskt = gimple_assign_rhs2 (def_stmt); + if (TREE_CODE (maskt) != INTEGER_CST) + return false; + + wide_int mask = maskt; + wide_int inv_mask = ~mask; + wide_int val = valt; // Assume VALT is INTEGER_CST + + if ((inv_mask & (inv_mask + 1)) != 0 + || (val & mask) != val) + return false; + + tree t = gimple_assign_rhs1 (def_stmt); + tree type = TREE_TYPE (t); + + bool is_range = cond_code == EQ_EXPR; + + wide_int min = wi::min_value (type), + max = wi::max_value (type); + + if (is_range) + { + *low_code = val == min ? ERROR_MARK : GE_EXPR; + *high_code = val == max ? ERROR_MARK : LE_EXPR; + } + else + { + /* We can still generate assertion if one of alternatives + is known to always be false. */ + if (val == min) + { + *low_code = (enum tree_code) 0; + *high_code = GT_EXPR; + } + else if ((val | inv_mask) == max) + { + *low_code = LT_EXPR; + *high_code = (enum tree_code) 0; + } + else + return false; + } + + *new_name = t; + *low = wide_int_to_tree (type, val); + *high = wide_int_to_tree (type, val | inv_mask); + + if (wi::neg_p (val, TYPE_SIGN (type))) + std::swap (*low, *high); + + return true; +} + /* Try to register an edge assertion for SSA name NAME on edge E for the condition COND contributing to the conditional jump pointed to by SI. */ @@ -5700,6 +5776,24 @@ register_edge_assert_for (tree name, edge e, register_edge_assert_for_1 (op1, EQ_EXPR, e, asserts); } } + + /* Sometimes we can infer ranges from (NAME & MASK) == VALUE. */ + if ((comp_code == EQ_EXPR || comp_code == NE_EXPR) + && TREE_CODE (val) == INTEGER_CST) + { + enum tree_code low_code, high_code; + tree low, high; + if (is_masked_range_test (name, val, comp_code, &name, &low, + &low_code, &high, &high_code)) + { + if (low_code != ERROR_MARK) + register_edge_assert_for_2 (name, e, low_code, name, + low, /*invert*/false, asserts); + if (high_code != ERROR_MARK) + register_edge_assert_for_2 (name, e, high_code, name, + high, /*invert*/false, asserts); + } + } } /* Finish found ASSERTS for E and register them at GSI. */ diff --git a/libgo/go/runtime/cgo_gccgo.go b/libgo/go/runtime/cgo_gccgo.go index a55fb43..b0ad2f1 100644 --- a/libgo/go/runtime/cgo_gccgo.go +++ b/libgo/go/runtime/cgo_gccgo.go @@ -54,7 +54,7 @@ func CgocallDone() { // If we are invoked because the C function called _cgo_panic, // then _cgo_panic will already have exited syscall mode. - if gp.atomicstatus == _Gsyscall { + if readgstatus(gp)&^_Gscan == _Gsyscall { exitsyscall(0) } diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 64735e2..32bc148 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -1459,7 +1459,7 @@ func dropm() { // gccgo sets the stack to Gdead here, because the splitstack // context is not initialized. - mp.curg.atomicstatus = _Gdead + atomic.Store(&mp.curg.atomicstatus, _Gdead) mp.curg.gcstack = nil mp.curg.gcnextsp = nil @@ -2251,6 +2251,7 @@ func goexit0(gp *g) { casgstatus(gp, _Grunning, _Gdead) if isSystemGoroutine(gp) { atomic.Xadd(&sched.ngsys, -1) + gp.isSystemGoroutine = false } gp.m = nil gp.lockedm = nil diff --git a/libgo/go/runtime/traceback_gccgo.go b/libgo/go/runtime/traceback_gccgo.go index fb51043..0da5171 100644 --- a/libgo/go/runtime/traceback_gccgo.go +++ b/libgo/go/runtime/traceback_gccgo.go @@ -94,7 +94,7 @@ func showframe(name string, gp *g) bool { // We want to print those in the traceback. // But unless GOTRACEBACK > 1 (checked below), still skip // internal C functions and cgo-generated functions. - if !contains(name, ".") && !hasprefix(name, "__go_") && !hasprefix(name, "_cgo_") { + if name != "" && !contains(name, ".") && !hasprefix(name, "__go_") && !hasprefix(name, "_cgo_") { return true } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0408210..05efaa0 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,44 @@ +2017-06-12 Pedro Alves <palves@redhat.com> + + * doc/xml/manual/status_cxx2017.xml: Update C++17 constexpr + char_traits status. + * doc/html/*: Regenerate. + + * include/bits/char_traits.h (_GLIBCXX_ALWAYS_INLINE): Define if + not already defined. + (__cpp_lib_constexpr_char_traits): Uncomment. + (__constant_string_p, __constant_char_array_p): New. + (std::char_traits<char>, std::char_traits<wchar_t>): Add + _GLIBCXX17_CONSTEXPR on compare, length and find and use + __constant_string_p, __constant_char_array_p and + __builtin_constant_p to defer to __gnu_cxx::char_traits at compile + time. + + * testsuite/21_strings/char_traits/requirements/ + constexpr_functions_c++17.cc: Uncomment + __cpp_lib_constexpr_char_traits tests. Uncomment + test_compare<char>, test_length<char>, test_find<char>, + test_compare<wchar_t>, test_length<wchar_t> and test_find<wchar_t> + static_assert tests. + +2017-06-12 François Dumont <fdumont@gcc.gnu.org> + + * include/bits/stl_tree.h (_Rb_tree_impl()): Restore _Node_allocator + default init. + * testsuite/util/testsuite_allocator.h + (__gnu_test::default_init_allocator<>) New. + * testsuite/23_containers/set/allocator/default_init.cc: New. + * testsuite/23_containers/map/allocator/default_init.cc: New. + +2017-06-12 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/55917 + * src/c++11/thread.cc (execute_native_thread_routine): Remove + try-block so that exceptions propagate out of the thread and terminate + is called by the exception-handling runtime. + (execute_native_thread_routine_compat): Likewise. + * testsuite/30_threads/thread/cons/terminate.cc: New. + 2017-06-09 Jonathan Wakely <jwakely@redhat.com> * doc/xml/manual/intro.xml: Document LWG 2802, 2873 and 2942 changes. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index a208238..85e193d 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -482,15 +482,14 @@ Feature-testing recommendations for C++</link>. </row> <row> - <?dbhtml bgcolor="#B0B0B0" ?> <entry> Constexpr for <code>std::char_traits</code> </entry> <entry> <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0426r1.html"> P0426R1 </link> </entry> - <entry align="center"> 7 (partial) </entry> - <entry><code> ??? </code></entry> + <entry align="center"> 8 </entry> + <entry><code> __cpp_lib_constexpr_char_traits >= 201611 </code></entry> </row> <row> diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index f19120b..5ccb439 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -40,6 +40,10 @@ #include <bits/postypes.h> // For streampos #include <cwchar> // For WEOF, wmemmove, wmemset, etc. +#ifndef _GLIBCXX_ALWAYS_INLINE +#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -139,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } }; -// #define __cpp_lib_constexpr_char_traits 201611 +#define __cpp_lib_constexpr_char_traits 201611 template<typename _CharT> _GLIBCXX14_CONSTEXPR int @@ -212,6 +216,42 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __cplusplus > 201402 + /** + * @brief Determine whether the characters of a NULL-terminated + * string are known at compile time. + * @param __s The string. + * + * Assumes that _CharT is a built-in character type. + */ + template<typename _CharT> + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_string_p(const _CharT* __s) + { + while (__builtin_constant_p(*__s) && *__s) + __s++; + return __builtin_constant_p(*__s); + } + + /** + * @brief Determine whether the characters of a character array are + * known at compile time. + * @param __a The character array. + * @param __n Number of characters. + * + * Assumes that _CharT is a built-in character type. + */ + template<typename _CharT> + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_char_array_p(const _CharT* __a, size_t __n) + { + size_t __i = 0; + while (__builtin_constant_p(__a[__i]) && __i < __n) + __i++; + return __i == __n; + } +#endif + // 21.1 /** * @brief Basis for explicit traits specializations. @@ -256,21 +296,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION < static_cast<unsigned char>(__c2)); } - static /* _GLIBCXX17_CONSTEXPR */ int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); +#endif if (__n == 0) return 0; return __builtin_memcmp(__s1, __s2, __n); } - static /* _GLIBCXX17_CONSTEXPR */ size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) - { return __builtin_strlen(__s); } + { +#if __cplusplus > 201402 + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits<char_type>::length(__s); +#endif + return __builtin_strlen(__s); + } - static /* _GLIBCXX17_CONSTEXPR */ const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); +#endif if (__n == 0) return 0; return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); @@ -347,24 +405,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT { return __c1 < __c2; } - static /* _GLIBCXX17_CONSTEXPR */ int + static _GLIBCXX17_CONSTEXPR int compare(const char_type* __s1, const char_type* __s2, size_t __n) { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); +#endif if (__n == 0) return 0; - return wmemcmp(__s1, __s2, __n); + else + return wmemcmp(__s1, __s2, __n); } - static /* _GLIBCXX17_CONSTEXPR */ size_t + static _GLIBCXX17_CONSTEXPR size_t length(const char_type* __s) - { return wcslen(__s); } + { +#if __cplusplus > 201402 + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits<char_type>::length(__s); + else +#endif + return wcslen(__s); + } - static /* _GLIBCXX17_CONSTEXPR */ const char_type* + static _GLIBCXX17_CONSTEXPR const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); +#endif if (__n == 0) return 0; - return wmemchr(__s, __a, __n); + else + return wmemchr(__s, __a, __n); } static char_type* diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 3f133b0..c2417f1 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -572,11 +572,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Node_allocator& _M_get_Node_allocator() _GLIBCXX_NOEXCEPT - { return *static_cast<_Node_allocator*>(&this->_M_impl); } + { return this->_M_impl; } const _Node_allocator& _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT - { return *static_cast<const _Node_allocator*>(&this->_M_impl); } + { return this->_M_impl; } allocator_type get_allocator() const _GLIBCXX_NOEXCEPT @@ -685,13 +685,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; -#if __cplusplus < 201103L _Rb_tree_impl() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Node_allocator>::value + && is_nothrow_default_constructible<_Base_key_compare>::value ) + : _Node_allocator() { } -#else - _Rb_tree_impl() = default; - _Rb_tree_impl(_Rb_tree_impl&&) = default; -#endif _Rb_tree_impl(const _Rb_tree_impl& __x) : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x)) @@ -703,6 +702,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Node_allocator(__a), _Base_key_compare(__comp) { } #else + _Rb_tree_impl(_Rb_tree_impl&&) = default; + _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) { } diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc index 44a230a..4a94bdd 100644 --- a/libstdc++-v3/src/c++11/thread.cc +++ b/libstdc++-v3/src/c++11/thread.cc @@ -77,20 +77,7 @@ namespace std _GLIBCXX_VISIBILITY(default) execute_native_thread_routine(void* __p) { thread::_State_ptr __t{ static_cast<thread::_State*>(__p) }; - - __try - { - __t->_M_run(); - } - __catch(const __cxxabiv1::__forced_unwind&) - { - __throw_exception_again; - } - __catch(...) - { - std::terminate(); - } - + __t->_M_run(); return nullptr; } @@ -104,20 +91,7 @@ namespace std _GLIBCXX_VISIBILITY(default) // the thread state to a local object, breaking the reference cycle // created in thread::_M_start_thread. __local.swap(__t->_M_this_ptr); - - __try - { - __t->_M_run(); - } - __catch(const __cxxabiv1::__forced_unwind&) - { - __throw_exception_again; - } - __catch(...) - { - std::terminate(); - } - + __t->_M_run(); return nullptr; } #endif diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc index 014caa0..efd280f 100644 --- a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc @@ -74,20 +74,20 @@ template<typename CT> } #ifndef __cpp_lib_constexpr_char_traits -// #error Feature-test macro for constexpr char_traits is missing +# error Feature-test macro for constexpr char_traits is missing #elif __cpp_lib_constexpr_char_traits != 201611 -// #error Feature-test macro for constexpr char_traits has the wrong value +# error Feature-test macro for constexpr char_traits has the wrong value #endif static_assert( test_assign<std::char_traits<char>>() ); -// static_assert( test_compare<std::char_traits<char>>() ); -// static_assert( test_length<std::char_traits<char>>() ); -// static_assert( test_find<std::char_traits<char>>() ); +static_assert( test_compare<std::char_traits<char>>() ); +static_assert( test_length<std::char_traits<char>>() ); +static_assert( test_find<std::char_traits<char>>() ); #ifdef _GLIBCXX_USE_WCHAR_T static_assert( test_assign<std::char_traits<wchar_t>>() ); -// static_assert( test_compare<std::char_traits<wchar_t>>() ); -// static_assert( test_length<std::char_traits<wchar_t>>() ); -// static_assert( test_find<std::char_traits<wchar_t>>() ); +static_assert( test_compare<std::char_traits<wchar_t>>() ); +static_assert( test_length<std::char_traits<wchar_t>>() ); +static_assert( test_find<std::char_traits<wchar_t>>() ); #endif static_assert( test_assign<std::char_traits<char16_t>>() ); static_assert( test_compare<std::char_traits<char16_t>>() ); diff --git a/libstdc++-v3/testsuite/23_containers/map/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/map/allocator/default_init.cc new file mode 100644 index 0000000..1ef13d9 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/map/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library 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 this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } +// { dg-options "-O0" } +// { dg-xfail-run-if "PR c++/65816" { *-*-* } } + +#include <map> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +#include <ext/aligned_buffer.h> + +using T = int; + +using __gnu_test::default_init_allocator; + +void test01() +{ + typedef default_init_allocator<std::pair<const T, T>> alloc_type; + typedef std::map<T, T, std::less<T>, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type; + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +void test02() +{ + typedef default_init_allocator<std::pair<const T, T>> alloc_type; + typedef std::map<T, T, std::less<T>, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type(); + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/set/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/set/allocator/default_init.cc new file mode 100644 index 0000000..4e14e18 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/set/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library 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 this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } +// { dg-options "-O0" } +// { dg-xfail-run-if "PR c++/65816" { *-*-* } } + +#include <set> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +#include <ext/aligned_buffer.h> + +using T = int; + +using __gnu_test::default_init_allocator; + +void test01() +{ + typedef default_init_allocator<T> alloc_type; + typedef std::set<T, std::less<T>, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type; + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +void test02() +{ + typedef default_init_allocator<T> alloc_type; + typedef std::set<T, std::less<T>, alloc_type> test_type; + + __gnu_cxx::__aligned_buffer<test_type> buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type(); + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/30_threads/thread/cons/terminate.cc b/libstdc++-v3/testsuite/30_threads/thread/cons/terminate.cc new file mode 100644 index 0000000..4b35b6c --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/thread/cons/terminate.cc @@ -0,0 +1,48 @@ +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library 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 this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* powerpc-ibm-aix* } } +// { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* powerpc-ibm-aix* } } +// { dg-require-effective-target c++11 } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +#include <thread> +#include <exception> +#include <cstdlib> + +void handle_terminate() +{ + std::_Exit(0); +} + +void f() { throw 1; } + +void +test01() +{ + std::set_terminate(handle_terminate); + std::thread t(f); + t.join(); + std::abort(); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 56c2708..233ea0b 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -508,6 +508,38 @@ namespace __gnu_test bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&) { return false; } + template<typename T> + struct default_init_allocator + { + using value_type = T; + + default_init_allocator() = default; + + template<typename U> + default_init_allocator(const default_init_allocator<U>& a) + : state(a.state) + { } + + T* + allocate(std::size_t n) + { return std::allocator<T>().allocate(n); } + + void + deallocate(T* p, std::size_t n) + { std::allocator<T>().deallocate(p, n); } + + int state; + }; + + template<typename T, typename U> + bool operator==(const default_init_allocator<T>& t, + const default_init_allocator<U>& u) + { return t.state == u.state; } + + template<typename T, typename U> + bool operator!=(const default_init_allocator<T>& t, + const default_init_allocator<U>& u) + { return !(t == u); } #endif template<typename Tp> |