diff options
author | Martin Liska <mliska@suse.cz> | 2022-09-05 10:44:56 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-09-05 10:44:56 +0200 |
commit | d8e441f4b8698f38e4564fe1bbe9ff112814ecff (patch) | |
tree | 62aac45da0a2358e1ea29a07ab734f607a201e5b /gcc | |
parent | 4483fe115cef3eea1d64e913816e2d117b38ac73 (diff) | |
parent | ca60bd93e216ae0425f790e1d4f4dc4a48763c0e (diff) | |
download | gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.zip gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.tar.gz gcc-d8e441f4b8698f38e4564fe1bbe9ff112814ecff.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
739 files changed, 23045 insertions, 19310 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c07208a..77208a9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,1453 @@ +2022-09-04 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::union_): Do not drop properties when + unioning a NAN with something else. + (range_tests_signed_zeros): Add tests. + +2022-09-04 Aldy Hernandez <aldyh@redhat.com> + + * real.cc (encode_ieee_single): Use real_isdenormal. + (encode_ieee_double): Same. + (encode_ieee_extended): Same. + (encode_ieee_quad): Same. + (encode_ieee_half): Same. + (encode_arm_bfloat_half): Same. + * real.h (real_isdenormal): New. + +2022-09-03 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (frange::singleton_p): Move NAN check to the top. + +2022-09-03 Jan-Benedict Glaw <jbglaw@lug-owl.de> + + * config/nvptx/nvptx.h (ASM_OUTPUT_DEF): Reference macro arguments. + +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_DOACROSS. + (enum omp_clause_depend_kind): Remove OMP_CLAUSE_DEPEND_SOURCE + and OMP_CLAUSE_DEPEND_SINK, add OMP_CLAUSE_DEPEND_INVALID. + (enum omp_clause_doacross_kind): New type. + (struct tree_omp_clause): Add subcode.doacross_kind member. + * tree.h (OMP_CLAUSE_DEPEND_SINK_NEGATIVE): Remove. + (OMP_CLAUSE_DOACROSS_KIND): Define. + (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE): Define. + (OMP_CLAUSE_DOACROSS_DEPEND): Define. + (OMP_CLAUSE_ORDERED_DOACROSS): Define. + * tree.cc (omp_clause_num_ops, omp_clause_code_name): Add + OMP_CLAUSE_DOACROSS entries. + * tree-nested.cc (convert_nonlocal_omp_clauses, + convert_local_omp_clauses): Handle OMP_CLAUSE_DOACROSS. + * tree-pretty-print.cc (dump_omp_clause): Don't handle + OMP_CLAUSE_DEPEND_SOURCE and OMP_CLAUSE_DEPEND_SINK. Handle + OMP_CLAUSE_DOACROSS. + * gimplify.cc (gimplify_omp_depend): Don't handle + OMP_CLAUSE_DEPEND_SOURCE and OMP_CLAUSE_DEPEND_SINK. + (gimplify_scan_omp_clauses): Likewise. Handle OMP_CLAUSE_DOACROSS. + (gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_DOACROSS. + (find_standalone_omp_ordered): New function. + (gimplify_omp_for): When OMP_CLAUSE_ORDERED is present, search + body for OMP_ORDERED with OMP_CLAUSE_DOACROSS and if found, + set OMP_CLAUSE_ORDERED_DOACROSS. + (gimplify_omp_ordered): Don't handle OMP_CLAUSE_DEPEND_SINK or + OMP_CLAUSE_DEPEND_SOURCE, instead check OMP_CLAUSE_DOACROSS, adjust + diagnostics that presence or absence of ordered clause parameter + is irrelevant. Handle doacross(sink:omp_cur_iteration-1). Use + actual user name of the clause - doacross or depend - in diagnostics. + * omp-general.cc (omp_extract_for_data): Don't set fd->ordered + if !OMP_CLAUSE_ORDERED_DOACROSS (t). If + OMP_CLAUSE_ORDERED_DOACROSS (t) but !OMP_CLAUSE_ORDERED_EXPR (t), + set fd->ordered to -1 and set it after the loop in that case to + fd->collapse. + * omp-low.cc (check_omp_nesting_restrictions): Don't handle + OMP_CLAUSE_DEPEND_SOURCE nor OMP_CLAUSE_DEPEND_SINK, instead check + OMP_CLAUSE_DOACROSS. Use actual user name of the clause - doacross + or depend - in diagnostics. Diagnose mixing of stand-alone and + block associated ordered constructs binding to the same loop. + (lower_omp_ordered_clauses): Don't handle OMP_CLAUSE_DEPEND_SINK, + instead handle OMP_CLAUSE_DOACROSS. + (lower_omp_ordered): Look for OMP_CLAUSE_DOACROSS instead of + OMP_CLAUSE_DEPEND. + (lower_depend_clauses): Don't handle OMP_CLAUSE_DEPEND_SOURCE and + OMP_CLAUSE_DEPEND_SINK. + * omp-expand.cc (expand_omp_ordered_sink): Emit a sorry for + doacross(sink:omp_cur_iteration-1). + (expand_omp_ordered_source_sink): Use + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of + OMP_CLAUSE_DEPEND_SINK_NEGATIVE. Use actual user name of the clause + - doacross or depend - in diagnostics. + (expand_omp): Look for OMP_CLAUSE_DOACROSS clause instead of + OMP_CLAUSE_DEPEND. + (build_omp_regions_1): Likewise. + (omp_make_gimple_edges): Likewise. + * lto-streamer-out.cc (hash_tree): Handle OMP_CLAUSE_DOACROSS. + * tree-streamer-in.cc (unpack_ts_omp_clause_value_fields): Likewise. + * tree-streamer-out.cc (pack_ts_omp_clause_value_fields): Likewise. + +2022-09-02 David Malcolm <dmalcolm@redhat.com> + + PR c/90885 + * doc/invoke.texi (Warning Options): Add -Wxor-used-as-pow. + +2022-09-02 Iain Buclaw <ibuclaw@gdcproject.org> + + PR d/105659 + * config.gcc: Set tm_d_file to ${cpu_type}/${cpu_type}-d.h. + * config/aarch64/aarch64-d.cc: Include tm_d.h. + * config/aarch64/aarch64-protos.h (aarch64_d_target_versions): Move to + config/aarch64/aarch64-d.h. + (aarch64_d_register_target_info): Likewise. + * config/aarch64/aarch64.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/arm/arm-d.cc: Include tm_d.h and arm-protos.h instead of + tm_p.h. + * config/arm/arm-protos.h (arm_d_target_versions): Move to + config/arm/arm-d.h. + (arm_d_register_target_info): Likewise. + * config/arm/arm.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/default-d.cc: Remove memmodel.h include. + * config/freebsd-d.cc: Include tm_d.h instead of tm_p.h. + * config/glibc-d.cc: Likewise. + * config/i386/i386-d.cc: Include tm_d.h. + * config/i386/i386-protos.h (ix86_d_target_versions): Move to + config/i386/i386-d.h. + (ix86_d_register_target_info): Likewise. + (ix86_d_has_stdcall_convention): Likewise. + * config/i386/i386.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + (TARGET_D_HAS_STDCALL_CONVENTION): Likewise. + * config/i386/winnt-d.cc: Include tm_d.h instead of tm_p.h. + * config/mips/mips-d.cc: Include tm_d.h. + * config/mips/mips-protos.h (mips_d_target_versions): Move to + config/mips/mips-d.h. + (mips_d_register_target_info): Likewise. + * config/mips/mips.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/netbsd-d.cc: Include tm_d.h instead of tm.h and memmodel.h. + * config/openbsd-d.cc: Likewise. + * config/pa/pa-d.cc: Include tm_d.h. + * config/pa/pa-protos.h (pa_d_target_versions): Move to + config/pa/pa-d.h. + (pa_d_register_target_info): Likewise. + * config/pa/pa.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/riscv/riscv-d.cc: Include tm_d.h. + * config/riscv/riscv-protos.h (riscv_d_target_versions): Move to + config/riscv/riscv-d.h. + (riscv_d_register_target_info): Likewise. + * config/riscv/riscv.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/rs6000/rs6000-d.cc: Include tm_d.h. + * config/rs6000/rs6000-protos.h (rs6000_d_target_versions): Move to + config/rs6000/rs6000-d.h. + (rs6000_d_register_target_info): Likewise. + * config/rs6000/rs6000.h (TARGET_D_CPU_VERSIONS) Likewise.: + (TARGET_D_REGISTER_CPU_TARGET_INFO) Likewise.: + * config/s390/s390-d.cc: Include tm_d.h. + * config/s390/s390-protos.h (s390_d_target_versions): Move to + config/s390/s390-d.h. + (s390_d_register_target_info): Likewise. + * config/s390/s390.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * config/sol2-d.cc: Include tm_d.h instead of tm.h and memmodel.h. + * config/sparc/sparc-d.cc: Include tm_d.h. + * config/sparc/sparc-protos.h (sparc_d_target_versions): Move to + config/sparc/sparc-d.h. + (sparc_d_register_target_info): Likewise. + * config/sparc/sparc.h (TARGET_D_CPU_VERSIONS): Likewise. + (TARGET_D_REGISTER_CPU_TARGET_INFO): Likewise. + * configure: Regenerate. + * configure.ac (tm_d_file): Remove defaults.h. + (tm_d_include_list): Remove options.h and insn-constants.h. + * config/aarch64/aarch64-d.h: New file. + * config/arm/arm-d.h: New file. + * config/i386/i386-d.h: New file. + * config/mips/mips-d.h: New file. + * config/pa/pa-d.h: New file. + * config/riscv/riscv-d.h: New file. + * config/rs6000/rs6000-d.h: New file. + * config/s390/s390-d.h: New file. + * config/sparc/sparc-d.h: New file. + +2022-09-02 Aldy Hernandez <aldyh@redhat.com> + + * builtins.cc (fold_builtin_inf): Convert use of real_info to dconstinf. + (fold_builtin_fpclassify): Same. + * fold-const-call.cc (fold_const_call_cc): Same. + * match.pd: Same. + * omp-low.cc (omp_reduction_init_op): Same. + * realmpfr.cc (real_from_mpfr): Same. + * tree.cc (build_complex_inf): Same. + +2022-09-02 Peter Bergner <bergner@linux.ibm.com> + + * config/rs6000/rs6000-builtin.cc (rs6000_gimple_fold_mma_builtin): Use + NOP_EXPR for MMA pointer casting. + +2022-09-02 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-slp.cc (vect_optimize_slp_pass::internal_node_cost): + Reduce the fallback cost to 1. Only use it if the number of + input lanes is equal to the number of output lanes. + +2022-09-02 Richard Sandiford <richard.sandiford@arm.com> + + PR tree-optimization/106787 + * tree-vect-slp.cc (vect_map_to_instance): New function, split out + from... + (vect_bb_partition_graph_r): ...here. Replace the visited set + with a map from nodes to instances. Ensure that a node only + appears in one partition. + (vect_bb_partition_graph): Update accordingly. + +2022-09-02 Richard Biener <rguenther@suse.de> + + * timevar.def (TV_TREE_RPO_VN): New. + * tree-ssa-sccvn.h (do_rpo_vn): Remove one overload. + * tree-ssa-sccvn.cc (do_rpo_vn_1): Rename the worker. + (do_rpo_vn): Unify the public API, track with TV_TREE_RPO_VN. + (pass_fre::execute): Adjust. + * tree-ssa-uninit.cc (execute_early_warn_uninitialized): Adjust. + +2022-09-02 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106809 + * tree-ssa-sccvn.cc (dominaged_by_p_w_unex): Check we have + more than one successor before doing extra work. + +2022-09-02 Kito Cheng <kito.cheng@sifive.com> + + * common/config/riscv/riscv-common.cc: Include <vector>. + (struct riscv_multi_lib_info_t): New. + (riscv_subset_list::match_score): Ditto. + (find_last_appear_switch): Ditto. + (prefixed_with): Ditto. + (struct multi_lib_info_t): Ditto. + (riscv_current_arch_str): Ditto. + (riscv_current_abi_str): Ditto. + (riscv_multi_lib_info_t::parse): Ditto. + (riscv_check_cond): Ditto. + (riscv_check_conds): Ditto. + (riscv_compute_multilib): Ditto. + (TARGET_COMPUTE_MULTILIB): Defined. + * config/riscv/elf.h (LIB_SPEC): Call riscv_multi_lib_check if + doing link. + (RISCV_USE_CUSTOMISED_MULTI_LIB): New. + * config/riscv/riscv.h (riscv_multi_lib_check): New. + (EXTRA_SPEC_FUNCTIONS): Add riscv_multi_lib_check. + * config/riscv/riscv-subset.h (riscv_subset_list::match_score): New. + +2022-09-02 Kito Cheng <kito.cheng@sifive.com> + + * common/common-target.def (compute_multilib): New. + * common/common-targhooks.h (default_compute_multilib): New. + * common/common-targhooks.cc (default_compute_multilib): New. + * doc/tm.texi.in (TARGET_COMPUTE_MULTILIB): New. + * doc/tm.texi: Regen. + * gcc.cc: Include common/common-target.h. + (set_multilib_dir) Call targetm_common.compute_multilib. + (SWITCH_LIVE): Move to opts.h. + (SWITCH_FALSE): Ditto. + (SWITCH_IGNORE): Ditto. + (SWITCH_IGNORE_PERMANENTLY): Ditto. + (SWITCH_KEEP_FOR_GCC): Ditto. + (struct switchstr): Ditto. + * opts.h (SWITCH_LIVE): Move from gcc.c. + (SWITCH_FALSE): Ditto. + (SWITCH_IGNORE): Ditto. + (SWITCH_IGNORE_PERMANENTLY): Ditto. + (SWITCH_KEEP_FOR_GCC): Ditto. + (struct switchstr): Ditto. + +2022-09-02 Martin Liska <mliska@suse.cz> + + * config/pdp11/pdp11.h (PREFERRED_DEBUGGING_TYPE): Disable + debugging format. + +2022-09-02 Martin Liska <mliska@suse.cz> + + * Makefile.in: Remove -gstabs option support, DBX-related + macros and DBX debugging info support. + * collect2.cc (scan_prog_file): Likewise. + * common.opt: Likewise. + * config.gcc: Likewise. + * config.in: Likewise. + * config/aarch64/aarch64-elf.h (DBX_DEBUGGING_INFO): Likewise. + * config/alpha/alpha.cc: Likewise. + * config/alpha/elf.h (ASM_SPEC): Likewise. + * config/arc/arc.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/arm/aout.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/arm/netbsd-elf.h (DBX_CONTIN_LENGTH): Likewise. + * config/darwin.h (DSYMUTIL_SPEC): Likewise. + (ASM_DEBUG_SPEC): Likewise. + (DBX_DEBUGGING_INFO): Likewise. + (DBX_USE_BINCL): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + (DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise. + * config/epiphany/epiphany.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/i386/bsd.h (DBX_NO_XREFS): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/i386/gas.h (DBX_NO_XREFS): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/ia64/ia64.h: Likewise. + * config/ia64/sysv4.h (DBX_DEBUGGING_INFO): Likewise. + * config/m68k/linux.h (DBX_CONTIN_LENGTH): Likewise. + * config/m68k/openbsd.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + (DBX_CONTIN_CHAR): Likewise. + * config/mips/mips.cc (mips_output_filename): Likewise. + (mips_option_override): Likewise. + * config/mips/mips.h (SUBTARGET_ASM_DEBUGGING_SPEC): Likewise. + (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + (DBX_REGISTER_NUMBER): Likewise. + (GP_DBX_FIRST): Likewise. + (FP_DBX_FIRST): Likewise. + (MD_DBX_FIRST): Likewise. + * config/nvptx/nvptx.cc: Likewise. + * config/openbsd.h (DBX_NO_XREFS): Likewise. + * config/pa/pa-64.h (DBX_DEBUGGING_INFO): Likewise. + * config/pa/pa.h (ASSEMBLER_DIALECT): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/pa/som.h (PREFERRED_DEBUGGING_TYPE): Likewise. + (DBX_USE_BINCL): Likewise. + (DBX_LINES_FUNCTION_RELATIVE): Likewise. + (DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise. + * config/pdp11/pdp11.cc: Likewise. + * config/pdp11/pdp11.h (DBX_DEBUGGING_INFO): Likewise. + (PREFERRED_DEBUGGING_TYPE): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + * config/rs6000/rs6000-builtin.cc: Likewise. + * config/rs6000/rs6000-call.cc: Likewise. + * config/rs6000/rs6000-logue.cc (defined): Likewise. + * config/rs6000/rs6000.cc (rs6000_option_override_internal): Likewise. + (HAVE_XCOFF_DWARF_EXTRAS): Likewise. + (rs6000_xcoff_declare_function_name): Likewise. + * config/rs6000/sysv4.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_FUNCTION_FIRST): Likewise. + * config/rs6000/xcoff.h (XCOFF_DEBUGGING_INFO): Likewise. + * config/rx/rx.h (DBX_DEBUGGING_INFO): Likewise. + * config/sh/elf.h (DBX_LINES_FUNCTION_RELATIVE): Likewise. + (DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END): Likewise. + * config/sol2.h (NO_DBX_BNSYM_ENSYM): Likewise. + * config/sparc/freebsd.h (DBX_CONTIN_CHAR): Likewise. + * config/sparc/netbsd-elf.h (DBX_CONTIN_CHAR): Likewise. + * config/sparc/sparc.h (DBX_CONTIN_LENGTH): Likewise. + * config/vax/vax.cc (vax_file_start): Likewise. + * config/vax/vax.h (DBX_DEBUGGING_INFO): Likewise. + (DBX_CONTIN_LENGTH): Likewise. + (DBX_CONTIN_CHAR): Likewise. + (DBX_NO_XREFS): Likewise. + (DBX_STATIC_STAB_DATA_SECTION): Likewise. + * config/vx-common.h (DBX_DEBUGGING_INFO): Likewise. + (XCOFF_DEBUGGING_INFO): Likewise. + * configure: Regenerate. Likewise. + * configure.ac: Likewise. + * debug.h: Likewise. + * doc/install.texi: Likewise. + * doc/invoke.texi: Likewise. + * doc/passes.texi: Likewise. + * doc/tm.texi: Likewise. + * doc/tm.texi.in: Likewise. + * dwarf2asm.cc (XCOFF_DEBUGGING_INFO): Likewise. + (dw2_asm_output_nstring): Likewise. + (USE_LINKONCE_INDIRECT): Likewise. + * dwarf2out.cc (XCOFF_DEBUGGING_INFO): Likewise. + (HAVE_XCOFF_DWARF_EXTRAS): Likewise. + (output_fde): Likewise. + (output_call_frame_info): Likewise. + (have_macinfo): Likewise. + (add_AT_loc_list): Likewise. + (add_AT_view_list): Likewise. + (output_compilation_unit_header): Likewise. + (output_pubnames): Likewise. + (output_aranges): Likewise. + (output_line_info): Likewise. + (output_macinfo): Likewise. + (dwarf2out_finish): Likewise. + (dwarf2out_early_finish): Likewise. + * final.cc (final_scan_insn_1): Likewise. + (rest_of_handle_final): Likewise. + * flag-types.h (enum debug_info_type): Likewise. + (DBX_DEBUG): Likewise. + (XCOFF_DEBUG): Likewise. + * function.cc (defined): Likewise. + * gcc.cc (defined): Likewise. + (ASM_DEBUG_SPEC): Likewise. + (ASM_DEBUG_OPTION_SPEC): Likewise. + * opts.cc (common_handle_option): Likewise. + (set_debug_level): Likewise. + * system.h (fancy_abort): Likewise. + * target-def.h (TARGET_ASM_CONSTRUCTOR): Likewise. + (TARGET_ASM_DESTRUCTOR): Likewise. + * toplev.cc (defined): Likewise. + * varasm.cc: Likewise. + * config/dbxcoff.h: Removed. + * config/dbxelf.h: Removed. + * dbxout.cc: Removed. + * dbxout.h: Removed. + * gstab.h: Removed. + * stab.def: Removed. + * xcoffout.cc: Removed. + * xcoffout.h: Removed. + +2022-09-02 Simon Rainer <gcc.gnu@vvalter.com> + + PR ipa/106627 + * config/i386/i386-features.cc (ix86_get_function_versions_dispatcher): + Set TREE_NOTHROW correctly for dispatcher declaration. + * config/rs6000/rs6000.cc (rs6000_get_function_versions_dispatcher): + Likewise. + +2022-09-01 Tamar Christina <tamar.christina@arm.com> + + PR other/106782 + * config/aarch64/aarch64.cc + (aarch64_vector_costs::prefer_unrolled_loop): Replace %u with + HOST_WIDE_INT_PRINT_UNSIGNED. + +2022-09-01 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-slp.cc (vect_build_slp_tree_2): When building a + VEC_PERM_EXPR of an existing vector, set the SLP_TREE_LANES + to the number of vector elements, if that's a known constant. + (vect_optimize_slp_pass::is_compatible_layout): Remove associated + comment about zero SLP_TREE_LANES. + (vect_optimize_slp_pass::start_choosing_layouts): Iterate over + all partition members when looking for potential layouts. + Handle existing permutes of fixed-length vectors. + +2022-09-01 UroÅ¡ Bizjak <ubizjak@gmail.com> + + PR target/106707 + * config/i386/i386.md (moves to/from AX_REG into xchg peephole2): + Do not convert a move pattern where both operands are AX_REG. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (build_le): Convert to dconst*inf. + (build_ge): Same. + * value-range.cc (frange::set_signbit): Same. + (frange::normalize_kind): Same. + (range_tests_floats): Same. + * value-range.h (vrp_val_max): Same. + (vrp_val_min): Same. + (frange::set_varying): Same. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + * emit-rtl.cc (init_emit_once): Initialize dconstinf and + dconstninf. + * real.h: Add dconstinf and dconstninf. + +2022-09-01 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (compute_control_dep_chain): + Remove cycle detection, instead avoid walking backedges. + +2022-09-01 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (compute_control_dep_chain): + New wrapping overload. + (uninit_analysis::init_use_preds): Simplify. + (uninit_analysis::init_from_phi_def): Likewise. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + * gimple-range-fold.cc + (fold_using_range::range_of_builtin_int_call): Add case for + CFN_BUILT_IN_SIGNBIT. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (foperator_equal::op1_range): Do not copy sign + bit. + (foperator_not_equal::op1_range): Same. + * value-query.cc (range_query::get_tree_range): Set sign bit. + * value-range-pretty-print.cc (vrange_printer::visit): Dump sign bit. + * value-range.cc (frange::set_signbit): New. + (frange::set): Adjust for sign bit. + (frange::normalize_kind): Same. + (frange::union_): Remove useless comment. + (frange::intersect): Same. + (frange::contains_p): Adjust for sign bit. + (frange::singleton_p): Same. + (frange::verify_range): Same. + (range_tests_signbit): New tests. + (range_tests_floats): Call range_tests_signbit. + * value-range.h (class frange_props): Add signbit + (class frange): Same. + +2022-09-01 Jakub Jelinek <jakub@redhat.com> + + PR other/106782 + * dumpfile.h (dump_printf_loc): Use ATTRIBUTE_GCC_DUMP_PRINTF (3, 4) + instead of ATTRIBUTE_GCC_DUMP_PRINTF (3, 0). + * tree-parloops.cc (parloops_is_slp_reduction): Cast pointers to + derived types of gimple to gimple * to avoid -Wformat warnings. + * tree-vect-loop-manip.cc (vect_set_loop_condition, + vect_update_ivs_after_vectorizer): Likewise. + * tree-vect-stmts.cc (vectorizable_load): Likewise. + * tree-vect-patterns.cc (vect_split_statement, + vect_recog_mulhs_pattern, vect_recog_average_pattern, + vect_determine_precisions_from_range, + vect_determine_precisions_from_users): Likewise. + * gimple-loop-versioning.cc + (loop_versioning::analyze_term_using_scevs): Likewise. + * tree-vect-slp.cc (vect_build_slp_tree_1): Likewise. + (vect_build_slp_tree): Cast slp_tree to void * to avoid + -Wformat warnings. + (optimize_load_redistribution_1, vect_match_slp_patterns, + vect_build_slp_instance, vect_optimize_slp_pass::materialize, + vect_optimize_slp_pass::dump, vect_slp_convert_to_external, + vect_slp_analyze_node_operations, vect_bb_partition_graph): Likewise. + (vect_print_slp_tree): Likewise. Also use + HOST_WIDE_INT_PRINT_UNSIGNED instead of %u. + * tree-vect-loop.cc (vect_determine_vectorization_factor, + vect_analyze_scalar_cycles_1, vect_analyze_loop_operations, + vectorizable_induction, vect_transform_loop): Cast pointers to derived + types of gimple to gimple * to avoid -Wformat warnings. + (vect_analyze_loop_2): Cast slp_tree to void * to avoid + -Wformat warnings. + (vect_estimate_min_profitable_iters): Use HOST_WIDE_INT_PRINT_UNSIGNED + instead of %d. + * tree-vect-slp-patterns.cc (vect_pattern_validate_optab): Use %G + instead of %T and STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (node)) + instead of SLP_TREE_DEF_TYPE (node). + +2022-09-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/106655 + * doc/invoke.texi (-Winvalid-utf8): Document it. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106785 + * value-range.cc (range_tests_nan): Adjust tests for !HONOR_NANS. + (range_tests_floats): Same. + +2022-09-01 konglin1 <lingling.kong@intel.com> + + * tree-if-conv.cc (is_cond_scalar_reduction): Add MULT_EXPR + recognition. + +2022-09-01 Peter Bergner <bergner@linux.ibm.com> + + PR target/101322 + * config/rs6000/rs6000-builtin.cc (rs6000_gimple_fold_mma_builtin): + Enforce the use of a valid MMA pointer type. + +2022-09-01 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.cc (riscv_conditional_register_usage): Add vector + registers. + +2022-09-01 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.cc (riscv_const_insns): Add cost of poly_int. + (riscv_output_move): Add csrr vlenb assembly. + * config/riscv/riscv.md (move_type): Add csrr vlenb type. + (ext): New attribute. + (ext_enabled): Ditto. + (enabled): Ditto. + +2022-09-01 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/constraints.md (TARGET_VECTOR ? V_REGS : NO_REGS): Add + "vr" constraint. + (TARGET_VECTOR ? VD_REGS : NO_REGS): Add "vd" constraint. + (TARGET_VECTOR ? VM_REGS : NO_REGS): Add "vm" constraint. + (vp): Add poly constraint. + +2022-09-01 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.h (enum reg_class): Change vype to vtype. + +2022-09-01 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.cc (riscv_convert_vector_bits): Change + configuration according to TARGET_MIN_VLEN. + * config/riscv/riscv.h (UNITS_PER_FP_REG): Fix comment. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * config.build: Remove deprecated ports. + * config.gcc: Likewise. + * config.host: Likewise. + * configure.ac: Likewise. + * configure: Regenerate. + * config/pa/pa-hpux10.h: Removed. + * config/pa/pa-hpux10.opt: Removed. + * config/pa/t-dce-thr: Removed. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * Makefile.in: Always install limits.h and syslimits.h to + include folder. + * configure.ac: Assign STMP_FIXINC blank if + --disable-fixincludes is used. + * configure: Regenerate. + +2022-08-31 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (predicate::init_from_control_deps): + Assert the guard_bb isn't empty and has more than one successor. + Drop appropriate parts of the predicate when an edge fails to + register a predicate. + (predicate::dump): Dump empty predicate as TRUE. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/90994 + * gimple-predicate-analysis.cc (predicate::init_from_control_deps): + Ignore exceptional control flow and skip the edge for the purpose of + predicate generation also for non-calls. + +2022-08-31 Aldy Hernandez <aldyh@redhat.com> + + * value-range-storage.cc (frange_storage_slot::set_frange): Save + endpoints. + (frange_storage_slot::get_frange): Restore endpoints. + * value-range-storage.h (class frange_storage_slot): Add endpoint + fields. + +2022-08-31 Martin Liska <mliska@suse.cz> + + PR tree-optimization/106789 + * range-op-float.cc (default_frelop_fold_range): Remove the + function. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * value-range.h: Add more override keywords. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * value-range.h: Add override. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/65244 + * gimple-predicate-analysis.h (predicate::init_from_control_deps): + Add argument to specify whether the predicate is for the USE. + * gimple-predicate-analysis.cc (predicate::init_from_control_deps): + Also include predicates effective fallthru control edges when + the predicate is for the USE. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/73550 + * gimple-predicate-analysis.cc (predicate::init_from_control_deps): + Sanitize debug dumping. Handle case labels with a CASE_HIGH. + (predicate::dump): Adjust for better readability. + +2022-08-31 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + Jakub Jelinek <jakub@redhat.com> + + * omp-simd-clone.cc (simd_clone_adjust_return_type, + simd_clone_adjust_argument_types): Use known_eq (veclen, 0U) + instead of known_eq (veclen, 0) to avoid -Wsign-compare warnings. + +2022-08-31 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-slp.cc (vect_optimize_slp_pass::dump): Remove bogus + argument. + +2022-08-31 zhongjuzhe <juzhe.zhong@rivai.ai> + + * tree-vect-loop-manip.cc (vect_gen_vector_loop_niters): Simply + initialize const_vf to 0. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * config.gcc: Remove cr16. + +2022-08-30 Martin Jambor <mjambor@suse.cz> + + * vec.h (array_slice): Add constructors for non-const reference to + heap vector and pointers to heap vectors. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (early_nan_resolve): Change comment. + (frange::union_): Handle union when one side is a NAN. + (range_tests_nan): Add tests for NAN union. + +2022-08-30 Andrew Stubbs <ams@codesourcery.com> + + * config/gcn/gcn.cc (gcn_simd_clone_compute_vecsize_and_simdlen): New. + (gcn_simd_clone_adjust): New. + (gcn_simd_clone_usable): New. + (TARGET_SIMD_CLONE_ADJUST): New. + (TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN): New. + (TARGET_SIMD_CLONE_USABLE): New. + +2022-08-30 Andrew Stubbs <ams@codesourcery.com> + + * doc/tm.texi: Regenerate. + * omp-simd-clone.cc (simd_clone_adjust_return_type): Allow zero + vecsize. + (simd_clone_adjust_argument_types): Likewise. + * target.def (compute_vecsize_and_simdlen): Document the new + vecsize_int and vecsize_float semantics. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * expmed.cc (store_bit_field_1): Fix byte offset calculation + for undefined structures. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * params.opt (-param=vect-max-layout-candidates=): New parameter. + * doc/invoke.texi (vect-max-layout-candidates): Document it. + * tree-vectorizer.h (auto_lane_permutation_t): New typedef. + (auto_load_permutation_t): Likewise. + * tree-vect-slp.cc (vect_slp_node_weight): New function. + (slpg_layout_cost): New class. + (slpg_vertex): Replace perm_in and perm_out with partition, + out_degree, weight and out_weight. + (slpg_partition_info, slpg_partition_layout_costs): New classes. + (vect_optimize_slp_pass): Likewise, cannibalizing some part of + the previous vect_optimize_slp. + (vect_optimize_slp): Use it. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * hash-traits.h (vec_hash_base): New class. + (vec_free_hash_base): Likewise. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * hash-traits.h (int_hash_base): New struct, split out from... + (int_hash): ...this class, which now inherits from int_hash_base. + * hash-map-traits.h (unbounded_hashmap_traits): Take a template + parameter for the key that provides hash and equality functions. + (unbounded_int_hashmap_traits): Turn into a type alias of + unbounded_hashmap_traits. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * graphds.cc (graphds_scc): Add a pass-back parameter for the + final node order. + * graphds.h (graphds_scc): Update prototype accordingly. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-slp.cc (vect_transform_slp_perm_load_1): Split out from... + (vect_transform_slp_perm_load): ...here. Use SLP_TREE_VECTYPE instead + of STMT_VINFO_VECTYPE. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-slp.cc (vectorizable_slp_permutation_1): Split out from... + (vectorizable_slp_permutation): ...here. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * tree-vect-stmts.cc (get_related_vectype_for_scalar_type): Check + that the requested number of units is interoperable with the requested + prevailing mode. + +2022-08-30 Martin Liska <mliska@suse.cz> + + * config.gcc: Remove the port. + * config/m32c/rtems.h: Removed. + +2022-08-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/73550 + * gimple-predicate-analysis.cc (predicate::init_from_control_deps): + Do not apply MAX_NUM_CHAINS again. + +2022-08-30 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (format_edge_vec): Dump + both source and destination. + (dump_dep_chains): Remove. + (uninit_analysis::init_use_preds): Remove redundant + dumping of chains. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * value-range-storage.cc (frange_storage_slot::get_frange): Use + frange_nan. + * value-range.cc (frange::set_nan): New. + (frange_nan): Move to header file. + (range_tests_nan): Adjust frange_nan callers to pass type. + New test. + * value-range.h (FRANGE_PROP_ACCESSOR): Remove. + (frange_nan): New. + +2022-08-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/67196 + * gimple-predicate-analysis.cc (uninit_analysis::is_use_guarded): + Simplify and normalize use prediates before first use. + +2022-08-30 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (dump_pred_chain): Fix + parentizing and AND prepending. + (predicate::dump): Do not dump the GENERIC expanded + predicate, properly parentize and prepend ORs to the + piecewise predicate dump. + (build_pred_expr): Remove. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (finite_operand_p): New. + (build_le): New. + (build_lt): New. + (build_ge): New. + (build_gt): New. + (foperator_equal::fold_range): New implementation with endpoints. + (foperator_equal::op1_range): Same. + (foperator_not_equal::fold_range): Same. + (foperator_not_equal::op1_range): Same. + (foperator_lt::fold_range): Same. + (foperator_lt::op1_range): Same. + (foperator_lt::op2_range): Same. + (foperator_le::fold_range): Same. + (foperator_le::op1_range): Same. + (foperator_le::op2_range): Same. + (foperator_gt::fold_range): Same. + (foperator_gt::op1_range): Same. + (foperator_gt::op2_range): Same. + (foperator_ge::fold_range): Same. + (foperator_ge::op1_range): Same. + (foperator_ge::op2_range): Same. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (frange_set_nan): New. + (frange_drop_inf): New. + (frange_drop_ninf): New. + (foperator_equal::op1_range): Adjust for endpoints. + (foperator_lt::op1_range): Same. + (foperator_lt::op2_range): Same. + (foperator_gt::op1_range): Same. + (foperator_gt::op2_range): Same. + (foperator_unordered::op1_range): Same. + * value-query.cc (range_query::get_tree_range): Same. + * value-range-pretty-print.cc (vrange_printer::visit): Same. + * value-range-storage.cc (frange_storage_slot::get_frange): Same. + * value-range.cc (frange::set): Same. + (frange::normalize_kind): Same. + (frange::union_): Same. + (frange::intersect): Same. + (frange::operator=): Same. + (early_nan_resolve): New. + (frange::contains_p): New. + (frange::singleton_p): New. + (frange::set_nonzero): New. + (frange::nonzero_p): New. + (frange::set_zero): New. + (frange::zero_p): New. + (frange::set_nonnegative): New. + (frange_float): New. + (frange_nan): New. + (range_tests_nan): New. + (range_tests_signed_zeros): New. + (range_tests_floats): New. + (range_tests): New. + * value-range.h (frange::lower_bound): New. + (frange::upper_bound): New. + (vrp_val_min): Use real_inf with a sign instead of negating inf. + (frange::frange): New. + (frange::set_varying): Adjust for endpoints. + (real_max_representable): New. + (real_min_representable): New. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * match.pd ((cmp @0 zerop) real_zerop (negate@1 @0)): Add variant + for real zero. + +2022-08-30 Martin Liska <mliska@suse.cz> + + * config/s390/s390.cc (s390_rtx_costs): Use proper type as + argument. + +2022-08-30 Richard Biener <rguenther@suse.de> + + * tree-ssa-uninit.cc (warn_uninitialized_vars): Pre-compute + the set of fallthru reachable blocks from function entry + and use that to determine wlims.always_executed. + +2022-08-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56654 + * tree-ssa-uninit.cc (cand_cmp): New. + (find_uninit_use): First process all PHIs and collect candidate + stmts, then sort those after RPO. + (warn_uninitialized_phi): Pass on bb_to_rpo. + (execute_late_warn_uninitialized): Compute and pass on + reverse lookup of RPO number from basic block index. + +2022-08-30 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.h (uninit_analysis::operator()): + Remove. + * gimple-predicate-analysis.cc + (uninit_analysis::collect_phi_def_edges): Use phi_arg_set, + simplify a bit. + * tree-ssa-uninit.cc (defined_args): New global. + (compute_uninit_opnds_pos): Mask with the recorded set + of guarded maybe-uninitialized uses. + (uninit_undef_val_t::operator()): Remove. + (find_uninit_use): Process all PHI uses, recording the + guarded ones and marking the PHI result as uninitialized + consistently. + (warn_uninitialized_phi): Adjust. + (execute_late_warn_uninitialized): Get rid of the PHI worklist + and instead walk the function in RPO order. + * spellcheck.h (best_match::m_best_candidate_len): Initialize. + +2022-08-30 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/106744 + * tree-ssa-phiopt.cc (minmax_replacement): Correct arguments. + +2022-08-30 Tamar Christina <tamar.christina@arm.com> + + * expmed.cc (store_bit_field_1): Initialize regnum to 0. + +2022-08-29 David Faust <david.faust@oracle.com> + + PR target/106745 + * config/bpf/coreout.cc (bpf_core_get_sou_member_index): Fix + computation of index for anonymous members. + +2022-08-29 Jose E. Marchesi <jose.marchesi@oracle.com> + + * config/bpf/bpf.cc (bpf_target_macros): Define __bpf__ as a + target macro. + +2022-08-29 H.J. Lu <hjl.tools@gmail.com> + + PR target/106748 + * config/i386/i386-expand.cc + (ix86_avx256_split_vector_move_misalign): Handle E_V16BFmode. + * config/i386/sse.md (V_256H): Add V16BF. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * config/s390/s390.cc (s390_address_cost): Declare. + (s390_hard_regno_nregs): Declare. + (s390_rtx_costs): Add handling for REG and MEM in SET. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * config/s390/s390.cc (expand_perm_with_vpdi): Recognize swap pattern. + (is_reverse_perm_mask): New function. + (expand_perm_with_rot): Recognize reverse pattern. + (expand_perm_with_vstbrq): New function. + (expand_perm_with_vster): Use vler/vster for element reversal on z15. + (vectorize_vec_perm_const_1): Use. + (s390_vectorize_vec_perm_const): Add expand functions. + * config/s390/vx-builtins.md: Prefer vster over vler. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * config/s390/s390.md: Remove UNSPEC_VEC_EXTRACT. + * config/s390/vector.md: Rewrite patterns to use vec_select. + * config/s390/vx-builtins.md (vec_scatter_element<V_HW_2:mode>_SI): + Likewise. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + PR target/100869 + * config/s390/vector.md (@vpdi4_2<mode>): New pattern. + (rotl<mode>3_di): New pattern. + * config/s390/vx-builtins.md: Use vpdi and verll for reversing + elements. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * config/s390/s390.cc (s390_issue_rate): Add z15. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * common/config/s390/s390-common.cc: Enable -funroll-loops and + -munroll-only-small-loops for OPT_LEVELS_2_PLUS_SPEED_ONLY. + * config/s390/s390.cc (s390_loop_unroll_adjust): Do not unroll + loops larger than 12 instructions. + (s390_override_options_after_change): Set unroll options. + (s390_option_override_internal): Likewise. + * config/s390/s390.opt: Document munroll-only-small-loops. + +2022-08-29 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (is_loop_exit, + find_control_equiv_block): Inline into single caller ... + (uninit_analysis::init_use_preds): ... here and refactor. + +2022-08-29 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (compute_control_dep_chain): + Inline is_loop_exit and refactor, add comment about + loop exits. + +2022-08-29 Kito Cheng <kito.cheng@sifive.com> + + * config/riscv/riscv.cc (riscv_frame_info): Introduce `reset(void)`; + (riscv_frame_info::reset(void)): New. + (riscv_compute_frame_info): Use riscv_frame_info::reset instead + of memset when clean frame. + +2022-08-29 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.cc (riscv_v_ext_vector_mode_p): New function. + (riscv_classify_address): Disallow PLUS/LO_SUM/CONST_INT address types for RVV. + (riscv_address_insns): Add RVV modes condition. + (riscv_binary_cost): Ditto. + (riscv_rtx_costs): Adjust cost for RVV. + (riscv_secondary_memory_needed): Add RVV modes condition. + (riscv_hard_regno_nregs): Add RVV register allocation. + (riscv_hard_regno_mode_ok): Add RVV register allocation. + (riscv_class_max_nregs): Add RVV register allocation. + * config/riscv/riscv.h (DWARF_FRAME_REGNUM): Add VL/VTYPE and vector registers in Dwarf. + (UNITS_PER_V_REG): New macro. + (FIRST_PSEUDO_REGISTER): Adjust first pseudo num for RVV. + (V_REG_FIRST): New macro. + (V_REG_LAST): Ditto. + (V_REG_NUM): Ditto. + (V_REG_P): Ditto. + (VL_REG_P): Ditto. + (VTYPE_REG_P): Ditto. + (RISCV_DWARF_VL): Ditto. + (RISCV_DWARF_VTYPE): Ditto. + (enum reg_class): Add RVV register types. + (REG_CLASS_CONTENTS): Add RVV register types. + * config/riscv/riscv.md: Add VL/VTYPE register number constants. + +2022-08-29 zhongjuzhe <juzhe.zhong@rivai.ai> + + * config/riscv/riscv.md: Add new type for vector instructions. + +2022-08-28 Peter Bergner <bergner@linux.ibm.com> + + PR target/106017 + * config/rs6000/rs6000.cc (rs6000_invalid_conversion): Remove handling + of MMA pointer conversions. + +2022-08-27 Xi Ruoyao <xry111@xry111.site> + + * config/i386/gcc-auto-profile: Regenerate. + +2022-08-26 Aldy Hernandez <aldyh@redhat.com> + + * real.cc (real_iszero): New. + * real.h (real_iszero): New. + +2022-08-26 Aldy Hernandez <aldyh@redhat.com> + + * real.cc (real_isinf): New overload. + (real_inf): Add sign argument. + * real.h (real_isinf): New overload. + (real_inf): Add sign argument. + +2022-08-26 Marek Polacek <polacek@redhat.com> + + PR c++/81159 + * doc/invoke.texi: Document -Wself-move. + +2022-08-26 Aldy Hernandez <aldyh@redhat.com> + + * value-range.cc (vrange::set): Set varying. + (vrange::set_nonzero): Same. + (vrange::set_zero): Same. + (vrange::set_nonnegative): Same. + +2022-08-26 Aldy Hernandez <aldyh@redhat.com> + + * range-op-float.cc (foperator_equal::op1_range): Do not blindly + copy op2 range when honoring signed zeros. + +2022-08-26 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.cc (possibly_profitable_path_p): Always + add newline. + (profitable_path_p): Same. + +2022-08-26 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.h + (uninit_analysis::use_cannot_happen): Remove. + * gimple-predicate-analysis.cc (can_be_invalidated_p): Remove. + (uninit_analysis::use_cannot_happen): Likewise. + (uninit_analysis::is_use_guarded): Do not call + use_cannot_happen. + (dump_predicates): Remove. + (simple_control_dep_chain): Remove edge overload. + +2022-08-26 Tobias Burnus <tobias@codesourcery.com> + + * internal-fn.cc (expand_GOMP_TARGET_REV): New. + * internal-fn.def (GOMP_TARGET_REV): New. + * lto-cgraph.cc (lto_output_node, verify_node_partition): Mark + 'omp target device_ancestor_host' as in_other_partition and don't + error if absent. + * omp-low.cc (create_omp_child_function): Mark as 'noclone'. + * omp-expand.cc (expand_omp_target): For reverse offload, remove + sorry, use device = GOMP_DEVICE_HOST_FALLBACK and create + empty-body nohost function. + * omp-offload.cc (execute_omp_device_lower): Handle + IFN_GOMP_TARGET_REV. + (pass_omp_target_link::execute): For ACCEL_COMPILER, don't + nullify fn argument for reverse offload + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + * builtins.def (BUILT_IN_ISSIGNALING): New built-in. + * builtins.cc (expand_builtin_issignaling): New function. + (expand_builtin_signbit): Don't overwrite target. + (expand_builtin): Handle BUILT_IN_ISSIGNALING. + (fold_builtin_classify): Likewise. + (fold_builtin_1): Likewise. + * optabs.def (issignaling_optab): New. + * fold-const-call.cc (fold_const_call_ss): Handle + BUILT_IN_ISSIGNALING. + * config/i386/i386.md (issignalingxf2): New expander. + * doc/extend.texi (__builtin_issignaling): Document. + (__builtin_isinf, __builtin_isnan): Clarify behavior with + -ffinite-math-only. + * doc/md.texi (issignaling<mode>2): Likewise. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/106099 + * internal-fn.def (TRAP): Add ECF_LOOPING_CONST_OR_PURE flag. + * tree-cfg.cc (execute_fixup_cfg): Add IFN_TRAP instead of + __builtin_trap to avoid the need of vops. + +2022-08-26 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (dfs_mark_dominating_region): + New helper. + (compute_control_dep_chain): Adjust to honor marked region + if provided. + (uninit_analysis::init_from_phi_def): Pre-mark the dominating + region to improve compute_control_dep_chain walking. + * vec.h (vec<T, va_heap, vl_ptr>::allocated): Add forwarder. + +2022-08-26 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc + (uninit_analysis::collect_phi_def_edges): Only expand a + PHI def edge when it is possibly undefined. + +2022-08-26 Martin Liska <mliska@suse.cz> + + * doc/extend.texi: Remove cr16 related stuff. + * doc/install.texi: Likewise. + * doc/invoke.texi: Likewise. + * doc/md.texi: Likewise. + * function-tests.cc (test_expansion_to_rtl): Likewise. + * common/config/cr16/cr16-common.cc: Removed. + * config/cr16/constraints.md: Removed. + * config/cr16/cr16-protos.h: Removed. + * config/cr16/cr16.cc: Removed. + * config/cr16/cr16.h: Removed. + * config/cr16/cr16.md: Removed. + * config/cr16/cr16.opt: Removed. + * config/cr16/predicates.md: Removed. + * config/cr16/t-cr16: Removed. + +2022-08-26 liuhongt <hongtao.liu@intel.com> + + PR target/106704 + * config/i386/i386-builtin.def (BDESC): Add + CODE_FOR_avx_blendvpd256/CODE_FOR_avx_blendvps256 to + corresponding builtins. + * config/i386/i386.cc (ix86_gimple_fold_builtin): + Don't fold IX86_BUILTIN_PBLENDVB256, IX86_BUILTIN_BLENDVPS256, + IX86_BUILTIN_BLENDVPD256 w/o TARGET_AVX2. + +2022-08-25 Marek Polacek <polacek@redhat.com> + + * ginclude/stddef.h: Define nullptr_t. + +2022-08-25 Joseph Myers <joseph@codesourcery.com> + + * gimplify.cc (gimplify_modify_expr): Convert initialization from + a variable-size CONSTRUCTOR to memset before call to + gimplify_modify_expr_rhs. + +2022-08-25 Jason Merrill <jason@redhat.com> + + * dwarf2out.cc (base_type_die): Also use DW_ATE_UTF for char8_t. + +2022-08-25 Andreas Krebbel <krebbel@linux.ibm.com> + + PR target/106101 + * config/s390/predicates.md (subreg_register_operand): New + predicate. + * config/s390/s390-protos.h (s390_gen_lowpart_subreg): New + function prototype. + * config/s390/s390.cc (s390_gen_lowpart_subreg): New function. + (s390_expand_insv): Use s390_gen_lowpart_subreg instead of + gen_lowpart. + * config/s390/s390.md ("*get_tp_64", "*zero_extendhisi2_31") + ("*zero_extendqisi2_31", "*zero_extendqihi2_31"): Likewise. + ("movstrictqi", "movstricthi", "movstrictsi"): Use the + subreg_register_operand predicate instead of register_operand. + +2022-08-25 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/loongarch-protos.h (loongarch_symbol_type): + Add SYMBOL_PCREL64 and change the description for SYMBOL_PCREL. + * config/loongarch/loongarch.cc (loongarch_attribute_table): + New attribute table. + (TARGET_ATTRIBUTE_TABLE): Define the target hook. + (loongarch_handle_model_attribute): New static function. + (loongarch_classify_symbol): Take TARGET_CMODEL_EXTREME and the + model attribute of SYMBOL_REF_DECL into account returning + SYMBOL_PCREL or SYMBOL_PCREL64. + (loongarch_use_anchors_for_symbol_p): New static function. + (TARGET_USE_ANCHORS_FOR_SYMBOL_P): Define the target hook. + (loongarch_symbol_extreme_p): New static function. + (loongarch_symbolic_constant_p): Handle SYMBOL_PCREL64. + (loongarch_symbol_insns): Likewise. + (loongarch_split_symbol_type): Likewise. + (loongarch_split_symbol): Check SYMBOL_PCREL64 instead of + TARGET_CMODEL_EXTREME for PC-relative addressing. + (loongarch_print_operand_reloc): Likewise. + * doc/extend.texi (Variable Attributes): Document new + LoongArch specific attribute. + +2022-08-25 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/loongarch.cc (loongarch_classify_symbol): + Return early if the rtx is not SYMBOL_REF. + +2022-08-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106737 + * tree-parloops.cc (transform_to_exit_first_loop_alt): Do not + verify SSA form. + +2022-08-25 Chenghua Xu <xuchenghua@loongson.cn> + + PR target/106459 + * config/loongarch/loongarch.cc (loongarch_build_integer): + Use HOST_WIDE_INT. + * config/loongarch/loongarch.h (IMM_REACH): Likewise. + (HWIT_1U): New Defined. + (LU12I_OPERAND): Use HOST_WIDE_INT. + (LU32I_OPERAND): Likewise. + (LU52I_OPERAND): Likewise. + (HWIT_UC_0xFFF): Likwise. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106632 + PR target/106588 + * config/riscv/bitmanip.md (*shNadduw): Use n constraint + instead of i. + (*slliuw): Likewise. + (*bexti): Likewise. Also add a check for operands[2] to be less + than the mode bitsize. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/constraints.md (DbS): New constraint. + (DnS): New constraint. + * config/riscv/bitmanip.md (*bset<mode>_1_mask): Use new constraint. + (*bclr<mode>): Likewise. + (*binvi<mode>): Likewise. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106586 + * config/riscv/predicates.md (single_bit_mask_operand): + Use SINGLE_BIT_MASK_OPERAND instead of directly calling pow2p_hwi. + (not_single_bit_mask_operand): Likewise. + * config/riscv/riscv.cc (riscv_build_integer_1): Don't special case + 1<<31 for 32bits as it is already handled. + Call trunc_int_for_mode on the upper part after the subtraction. + (riscv_move_integer): Call trunc_int_for_mode before generating + the integer just make sure the constant has been sign extended + corectly. + (riscv_emit_int_compare): Call trunc_int_for_mode after doing the + addition for the new rhs. + * config/riscv/riscv.h (SINGLE_BIT_MASK_OPERAND): If !TARGET64BIT, + then mask off the upper 32bits of the HWI as it will be sign extended. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/constraints.md (DsS): New constraint. + (DsD): New constraint. + * config/riscv/iterators.md (shiftm1c): New iterator. + * config/riscv/bitmanip.md (*bset<mode>_mask): + Use shiftm1c. + (*bset<mode>_1_mask): Likewise. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/constraints.md (Ds3): New constraint. + * config/riscv/predicates.md (imm123_operand): New predicate. + * config/riscv/bitmanip.md (*shNadd): Use Ds3 and imm123_operand. + (*shNadduw): Likewise. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/riscv.cc (riscv_print_operand): + Handle '~'. + (riscv_print_operand_punct_valid_p): New function + (TARGET_PRINT_OPERAND_PUNCT_VALID_P): Define. + * config/riscv/bitmanip.md (<bitmanip_optab>si2/clz_ctz_pcnt): + Use %~ instead of conditional the pattern on TARGET_64BIT. + (rotrsi3): Likewise. + (rotlsi3): Likewise. + * config/riscv/riscv.md: Add ~ to the list of modifiers. + (addsi3): Use %~ instead of conditional the pattern on TARGET_64BIT. + (subsi3): Likewise. + (negsi2): Likewise. + (mulsi3): Likewise. + (optab>si3/any_div): Likewise. + (*add<mode>hi3): Likewise. + (<optab>si3/any_shift): Likewise. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/riscv.cc (riscv_print_operand): Make a mention to + keep the list in riscv.md in sync with this list. + * config/riscv/riscv.md: Add list of modifiers as comments. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/sync.md (any_atomic, atomic_optab): Move to ... + * config/riscv/iterators.md: Here. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/bitmanip.md + (bitmanip_bitwise, bitmanip_minmax, clz_ctz_pcna, + tbitmanip_optab, bitmanip_insn, shiftm1): Move to ... + * config/riscv/iterators.md: Here. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * config/riscv/riscv.md (GPR): Move to new file. + (P, X, BR): Likewise. + (MOVE32, MOVE64, SHORT): Likewise. + (HISI, SUPERQI, SUBX): Likewise. + (ANYI, ANYF, SOFTF): Likewise. + (size, load, default_load): Likewise. + (softload, store, softstore): Likewise. + (reg, fmt, ifmt, amo): Likewise. + (UNITMODE, HALFMODE): Likewise. + (RINT, rint_pattern, rint_rm): Likewise. + (QUIET_COMPARISON, quiet_pattern, QUIET_PATTERN): Likewise. + (any_extend, any_shiftrt, any_shift): Likewise. + (any_bitwise): Likewise. + (any_div, any_mod): Likewise. + (any_gt, any_ge, any_lt, any_le): Likewise. + (u, su): Likewise. + (optab, insn): Likewise. + * config/riscv/iterators.md: New file. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106601 + * config/riscv/bitmanip.md (bswaphi2): New pattern. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106600 + * config/riscv/bitmanip.md (bswap<mode>2): Remove + condition on TARGET_64BIT as X is already conditional there. + +2022-08-24 Joseph Myers <joseph@codesourcery.com> + + * tree.cc (build_real): Give DFP dconst0 the minimum quantum + exponent for the type. + +2022-08-24 Jose E. Marchesi <jose.marchesi@oracle.com> + + PR target/106733 + * config/bpf/bpf.cc (bpf_legitimate_address_p): Recognize integer + constants as legitimate addresses for functions. + (bpf_small_register_classes_for_mode_p): Define target hook. + +2022-08-24 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc: Move predicate normalization + after the comment documenting it. + +2022-08-24 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.h (predicate): Split out + non-predicate related functionality into .. + (uninit_analysis): .. this new class. + * gimple-predicate-analysis.cc: Refactor into two classes. + * tree-ssa-uninit.cc (find_uninit_use): Use uninit_analysis. + +2022-08-24 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (predicate::use_cannot_happen): + Do simple_control_dep_chain only up to cd_root, add the PHI + operand edge to the chains like init_from_phi_def does. + (predicate::is_use_guarded): Speedup early out, avoid half-way + initializing the PHI def predicate. + +2022-08-24 Jakub Jelinek <jakub@redhat.com> + + PR target/106721 + * config/i386/sse.md (shuffletype): Add V32BF, V16BF and V8BF entries. + Change V32HF, V16HF and V8HF entries from "f" to "i". + (iptr): Add V32BF, V16BF, V8BF and BF entries. + (i128vldq): Add V16HF and V16BF entries. + (avx512er_vmrcp28<mode><mask_name><round_saeonly_name>): Fix typo, + mask_opernad3 -> mask_operand3. + +2022-08-24 Martin Liska <mliska@suse.cz> + Jørgen Kvalsvik <j@lambda.is> + + * gcov.cc (add_line_counts): Add group functions to coverage + summary. + (accumulate_line_counts): Similarly for files. + +2022-08-24 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/genopts/loongarch-strings: Support code model medium. + * config/loongarch/genopts/loongarch.opt.in: Likewise. + * config/loongarch/loongarch-def.c: Likewise. + * config/loongarch/loongarch-def.h (CMODEL_LARGE): Likewise. + (CMODEL_EXTREME): Likewise. + (N_CMODEL_TYPES): Likewise. + (CMODEL_MEDIUM): Likewise. + * config/loongarch/loongarch-opts.cc: Likewise. + * config/loongarch/loongarch-opts.h (TARGET_CMODEL_MEDIUM): Likewise. + * config/loongarch/loongarch-str.h (STR_CMODEL_MEDIUM): Likewise. + * config/loongarch/loongarch.cc (loongarch_call_tls_get_addr): + Tls symbol Loading support medium mode. + (loongarch_legitimize_call_address): When medium mode, make a symbolic + jump with two instructions. + (loongarch_option_override_internal): Support medium. + * config/loongarch/loongarch.md (@pcalau12i<mode>): New template. + (@sibcall_internal_1<mode>): New function call templates added to support + medium mode. + (@sibcall_value_internal_1<mode>): Likewise. + (@sibcall_value_multiple_internal_1<mode>): Likewise. + (@call_internal_1<mode>): Likewise. + (@call_value_internal_1<mode>): Likewise. + (@call_value_multiple_internal_1<mode>): Likewise. + * config/loongarch/loongarch.opt: Support medium. + * config/loongarch/predicates.md: Add processing about medium mode. + * doc/invoke.texi: Document for '-mcmodel=medium'. + +2022-08-24 Richard Biener <rguenther@suse.de> + + * gimple-predicate-analysis.cc (predicate::use_cannot_happen): + Start the compute_control_dep_chain walk from the immediate + dominator of the PHI. + 2022-08-23 H.J. Lu <hjl.tools@gmail.com> PR target/106714 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a8087bc..6f5f711 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20220824 +20220905 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 203f0a1..d3b66b7 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1353,7 +1353,6 @@ OBJS = \ data-streamer.o \ data-streamer-in.o \ data-streamer-out.o \ - dbxout.o \ dbgcnt.o \ dce.o \ ddg.o \ @@ -1727,7 +1726,6 @@ OBJS = \ web.o \ wide-int.o \ wide-int-print.o \ - xcoffout.o \ $(out_object_file) \ $(ANALYZER_OBJS) \ $(EXTRA_OBJS) \ @@ -2676,7 +2674,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/reload.h $(srcdir)/caller-save.cc $(srcdir)/symtab.cc \ $(srcdir)/alias.cc $(srcdir)/bitmap.cc $(srcdir)/cselib.cc $(srcdir)/cgraph.cc \ $(srcdir)/ipa-prop.cc $(srcdir)/ipa-cp.cc $(srcdir)/ipa-utils.h \ - $(srcdir)/ipa-param-manipulation.h $(srcdir)/ipa-sra.cc $(srcdir)/dbxout.cc \ + $(srcdir)/ipa-param-manipulation.h $(srcdir)/ipa-sra.cc \ $(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.cc \ $(srcdir)/ipa-modref-tree.h \ $(srcdir)/signop.h \ @@ -3166,24 +3164,27 @@ stmp-int-hdrs: $(STMP_FIXINC) $(T_GLIMITS_H) $(T_STDINT_GCC_H) $(USER_H) fixinc_ set -e; for ml in `cat fixinc_list`; do \ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ - fix_dir=include-fixed$${multi_dir}; \ + include_dir=include$${multi_dir}; \ if $(LIMITS_H_TEST) ; then \ cat $(srcdir)/limitx.h $(T_GLIMITS_H) $(srcdir)/limity.h > tmp-xlimits.h; \ else \ cat $(T_GLIMITS_H) > tmp-xlimits.h; \ fi; \ - $(mkinstalldirs) $${fix_dir}; \ - chmod a+rx $${fix_dir} || true; \ + $(mkinstalldirs) $${include_dir}; \ + chmod a+rx $${include_dir} || true; \ $(SHELL) $(srcdir)/../move-if-change \ tmp-xlimits.h tmp-limits.h; \ - rm -f $${fix_dir}/limits.h; \ - cp -p tmp-limits.h $${fix_dir}/limits.h; \ - chmod a+r $${fix_dir}/limits.h; \ + rm -f $${include_dir}/limits.h; \ + cp -p tmp-limits.h $${include_dir}/limits.h; \ + chmod a+r $${include_dir}/limits.h; \ + cp $(srcdir)/gsyslimits.h $${include_dir}/syslimits.h; \ done # Install the README - rm -f include-fixed/README - cp $(srcdir)/../fixincludes/README-fixinc include-fixed/README - chmod a+r include-fixed/README + if [ x$(STMP_FIXINC) != x ]; then \ + rm -f include-fixed/README; \ + cp $(srcdir)/../fixincludes/README-fixinc include-fixed/README; \ + chmod a+r include-fixed/README; \ + fi; $(STAMP) $@ .PHONY: install-gcc-tooldir @@ -3268,13 +3269,6 @@ stmp-fixinc: gsyslimits.h macro_list fixinc_list \ cd $(build_objdir)/fixincludes && \ $(SHELL) ./fixinc.sh "$${gcc_dir}/$${fix_dir}" \ $(BUILD_SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS) ); \ - rm -f $${fix_dir}/syslimits.h; \ - if [ -f $${fix_dir}/limits.h ]; then \ - mv $${fix_dir}/limits.h $${fix_dir}/syslimits.h; \ - else \ - cp $(srcdir)/gsyslimits.h $${fix_dir}/syslimits.h; \ - fi; \ - chmod a+r $${fix_dir}/syslimits.h; \ done; \ fi $(STAMP) stmp-fixinc @@ -3992,7 +3986,7 @@ install-mkheaders: stmp-int-hdrs install-itoolsdirs \ set -e; for ml in `cat fixinc_list`; do \ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \ $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}; \ - $(INSTALL_DATA) include-fixed$${multi_dir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ + $(INSTALL_DATA) include$${multi_dir}/limits.h $(DESTDIR)$(itoolsdatadir)/include$${multi_dir}/limits.h; \ done $(INSTALL_SCRIPT) $(srcdir)/../mkinstalldirs \ $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 2469db4..7bad8a6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,96 @@ +2022-09-02 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.adb (Expand_Subtype_From_Expr): Be prepared for + rewritten aggregates as expressions. + +2022-09-02 Gary Dismukes <dismukes@adacore.com> + + * exp_ch6.adb (Expand_Simple_Function_Return) Bypass creation of an actual + subtype and unchecked conversion to that subtype when the underlying type + of the expression has discriminants without defaults. + +2022-09-02 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.adb (Expand_Subtype_From_Expr): Check for the presence + of the Is_Constr_Subt_For_U_Nominal flag instead of the absence + of the Is_Constr_Subt_For_UN_Aliased flag on the subtype of the + expression of an object declaration before reusing this subtype. + * sem_ch3.adb (Analyze_Object_Declaration): Do not incorrectly + set the Is_Constr_Subt_For_UN_Aliased flag on the actual subtype + of an array with definite nominal subtype. Remove useless test. + +2022-09-02 Eric Botcazou <ebotcazou@adacore.com> + + * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst + (No_Dependence): Cite implicit dependences on the runtime library. + * gnat_rm.texi, gnat_ugn.texi: Regenerate. + +2022-09-02 Claire Dross <dross@adacore.com> + + * libgnat/a-strmap.adb: Add variants to simple and while loops. + * libgnat/a-strsea.adb: Idem. + +2022-09-02 Claire Dross <dross@adacore.com> + + * libgnat/s-expmod.adb (Lemma_Add_Mod): Add new lemma to factor + out a complex sub-proof. + (Exp_Modular): Add assertion to help proof. + +2022-09-02 Claire Dross <dross@adacore.com> + + * libgnat/s-widthu.adb (Lemma_Euclidean): Lemma to prove the + relation between the quotient/remainder of a division. + +2022-09-02 Yannick Moy <moy@adacore.com> + + * libgnat/s-aridou.adb: Add or rework ghost code. + * libgnat/s-aridou.ads: Add Big_Positive subtype. + +2022-09-02 Eric Botcazou <ebotcazou@adacore.com> + + * doc/gnat_ugn/gnat_and_program_execution.rst + (Non-Symbolic Traceback): Update section. + * gnat_rm.texi, gnat_ugn.texi, gnat-style.texi: Regenerate. + +2022-09-02 Claire Dross <dross@adacore.com> + + * libgnat/a-nbnbig.ads: Add Always_Return annotation. + * libgnat/s-vaispe.ads: New ghost unit for the specification of + System.Value_I. Restore proofs. + * libgnat/s-vauspe.ads: New ghost unit for the specification of + System.Value_U. Restore proofs. + * libgnat/s-valuei.adb: The specification only subprograms are + moved to System.Value_I_Spec. Restore proofs. + * libgnat/s-valueu.adb: The specification only subprograms are + moved to System.Value_U_Spec. Restore proofs. + * libgnat/s-valuti.ads + (Uns_Params): Generic unit used to bundle together the + specification functions of System.Value_U_Spec. + (Int_Params): Generic unit used to bundle together the + specification functions of System.Value_I_Spec. + * libgnat/s-imagef.adb: It is now possible to instantiate the + appropriate specification units instead of creating imported ghost + subprograms. + * libgnat/s-imagei.adb: Update to refactoring of specifications + and fix proofs. + * libgnat/s-imageu.adb: Likewise. + * libgnat/s-imgint.ads: Ghost parameters are grouped together in a + package now. + * libgnat/s-imglli.ads: Likewise. + * libgnat/s-imgllu.ads: Likewise. + * libgnat/s-imgllli.ads: Likewise. + * libgnat/s-imglllu.ads: Likewise. + * libgnat/s-imguns.ads: Likewise. + * libgnat/s-vallli.ads: Likewise. + * libgnat/s-valllli.ads: Likewise. + * libgnat/s-imagei.ads: Likewise. + * libgnat/s-imageu.ads: Likewise. + * libgnat/s-vaispe.adb: Likewise. + * libgnat/s-valint.ads: Likewise. + * libgnat/s-valuei.ads: Likewise. + * libgnat/s-valueu.ads: Likewise. + * libgnat/s-vauspe.adb: Likewise. + 2022-07-13 Eric Botcazou <ebotcazou@adacore.com> * gcc-interface/trans.cc (gnat_to_gnu) <N_Assignment_Statement>: Fix diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb index bcc8822..3febd48 100644 --- a/gcc/ada/ali.adb +++ b/gcc/ada/ali.adb @@ -2079,15 +2079,24 @@ package body ALI is -- Processing for SS elsif C = 'S' then - -- Special case: a-tags.ali by itself should not set + -- Special case: a-tags/i-c* by themselves should not set -- Sec_Stack_Used, only if other code uses the secondary -- stack should we set this flag. This ensures that we do -- not bring the secondary stack unnecessarily when using - -- Ada.Tags and not actually using the secondary stack. + -- one of these packages and not actually using the + -- secondary stack. - if Get_Name_String (F) /= "a-tags.ali" then - Opt.Sec_Stack_Used := True; - end if; + declare + File : constant String := Get_Name_String (F); + begin + if File /= "a-tags.ali" + and then File /= "i-c.ali" + and then File /= "i-cstrin.ali" + and then File /= "i-cpoint.ali" + then + Opt.Sec_Stack_Used := True; + end if; + end; -- Invalid switch starting with S diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads index 6559cda..2edb608 100644 --- a/gcc/ada/aspects.ads +++ b/gcc/ada/aspects.ads @@ -822,11 +822,11 @@ package Aspects is -- set on the parent type if it has delayed representation aspects. This -- flag Has_Delayed_Rep_Aspects indicates that if we derive from this type -- we have to worry about making sure we inherit any delayed aspects. The - -- second flag is set on a derived type: May_Have_Inherited_Rep_Aspects + -- second flag is set on a derived type: May_Inherit_Delayed_Rep_Aspects -- is set if the parent type has Has_Delayed_Rep_Aspects set. - -- When we freeze a derived type, if the May_Have_Inherited_Rep_Aspects - -- flag is set, then we call Freeze.Inherit_Delayed_Rep_Aspects when + -- When we freeze a derived type, if the May_Inherit_Delayed_Rep_Aspects + -- flag is set, then we call Sem_Ch13.Inherit_Delayed_Rep_Aspects when -- the derived type is frozen, which deals with the necessary copying of -- information from the parent type, which must be frozen at that point -- (since freezing the derived type first freezes the parent type). diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb index c70268d..d5877c6 100644 --- a/gcc/ada/bindgen.adb +++ b/gcc/ada/bindgen.adb @@ -1544,6 +1544,7 @@ package body Bindgen is Check_Elab_Flag := Units.Table (Unum_Spec).Set_Elab_Entity + and then Check_Elaboration_Flags and then not CodePeer_Mode and then (Force_Checking_Of_Elaboration_Flags or Interface_Library_Unit diff --git a/gcc/ada/bindusg.adb b/gcc/ada/bindusg.adb index bfab985..3f99bae 100644 --- a/gcc/ada/bindusg.adb +++ b/gcc/ada/bindusg.adb @@ -156,6 +156,11 @@ package body Bindusg is (" -I- Don't look for sources & library files in default " & "directory"); + -- Line for -k switch + + Write_Line + (" -k Disable checking of elaboration flags"); + -- Line for -K switch Write_Line diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst index 9ca4057..f8e2a58 100644 --- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst +++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst @@ -184,7 +184,9 @@ No_Dependence .. index:: No_Dependence [RM 13.12.1] This restriction ensures at compile time that there are no -dependences on a library unit. +dependences on a library unit. For GNAT, this includes implicit implementation +dependences on units of the runtime library that are created by the compiler +to support specific constructs of the language. No_Direct_Boolean_Operators --------------------------- diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 5442d55..37b6e95 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -6534,6 +6534,22 @@ be presented in subsequent sections. ALI file named in the ``gnatbind`` command line. + .. index:: -k (gnatbind) + +:switch:`-k` + Disable checking of elaboration flags. When using :switch:`-n` + either explicitly or implicitly, :switch:`-F` is also implied, + unless :switch:`-k` is used. This switch should be used with care + and you should ensure manually that elaboration routines are not called + twice unintentionally. + + + .. index:: -K (gnatbind) + +:switch:`-K` + Give list of linker options specified for link. + + .. index:: -l (gnatbind) :switch:`-l` diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst index c514678..0d78e43 100644 --- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst +++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst @@ -756,12 +756,14 @@ for a complete list of supported platforms. .. rubric:: Tracebacks From an Unhandled Exception A runtime non-symbolic traceback is a list of addresses of call instructions. -To enable this feature you must use the :switch:`-E` -``gnatbind`` option. With this option a stack traceback is stored as part -of exception information. You can retrieve this information using the -``addr2line`` tool. +To enable this feature you must use the :switch:`-E` ``gnatbind`` option. With +this option a stack traceback is stored as part of exception information. -Here is a simple example: +You can translate this information using the ``addr2line`` tool, provided that +the program is compiled with debugging options (see :ref:`Switches_for_gcc`) +and linked at a fixed position with :switch:`-no-pie`. + +Here is a simple example with ``gnatmake``: .. code-block:: ada @@ -783,94 +785,110 @@ Here is a simple example: :: - $ gnatmake stb -bargs -E + $ gnatmake stb -g -bargs -E -largs -no-pie $ stb - Execution terminated by unhandled exception - Exception name: CONSTRAINT_ERROR - Message: stb.adb:5 + Execution of stb terminated by unhandled exception + raised CONSTRAINT_ERROR : stb.adb:5 explicit raise + Load address: 0x400000 Call stack traceback locations: 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 As we see the traceback lists a sequence of addresses for the unhandled exception ``CONSTRAINT_ERROR`` raised in procedure P1. It is easy to guess that this exception come from procedure P1. To translate these -addresses into the source lines where the calls appear, the -``addr2line`` tool, described below, is invaluable. The use of this tool -requires the program to be compiled with debug information. +addresses into the source lines where the calls appear, the ``addr2line`` +tool needs to be invoked like this: :: - $ gnatmake -g stb -bargs -E - $ stb - - Execution terminated by unhandled exception - Exception name: CONSTRAINT_ERROR - Message: stb.adb:5 - Call stack traceback locations: - 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 - - $ addr2line --exe=stb 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 + $ addr2line -e stb 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 - 00401373 at d:/stb/stb.adb:5 - 0040138B at d:/stb/stb.adb:10 - 0040139C at d:/stb/stb.adb:14 - 00401335 at d:/stb/b~stb.adb:104 - 004011C4 at /build/.../crt1.c:200 - 004011F1 at /build/.../crt1.c:222 - 77E892A4 in ?? at ??:0 + d:/stb/stb.adb:5 + d:/stb/stb.adb:10 + d:/stb/stb.adb:14 + d:/stb/b~stb.adb:197 + crtexe.c:? + crtexe.c:? + ??:0 The ``addr2line`` tool has several other useful options: - ======================== ======================================================== - :samp:`--functions` to get the function name corresponding to any location - :samp:`--demangle=gnat` to use the gnat decoding mode for the function names. - Note that for binutils version 2.9.x the option is - simply :samp:`--demangle`. - ======================== ======================================================== + ========================= ==================================================== + :samp:`-a --addresses` to show the addresses alongside the line numbers + :samp:`-f --functions` to get the function name corresponding to a location + :samp:`-p --pretty-print` to print all the information on a single line + :samp:`--demangle=gnat` to use the GNAT decoding mode for the function names + ========================= ==================================================== :: - $ addr2line --exe=stb --functions --demangle=gnat 0x401373 0x40138b - 0x40139c 0x401335 0x4011c4 0x4011f1 + $ addr2line -e stb -a -f -p --demangle=gnat 0x401373 0x40138b + 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 + + 0x00401373: stb.p1 at d:/stb/stb.adb:5 + 0x0040138B: stb.p2 at d:/stb/stb.adb:10 + 0x0040139C: stb at d:/stb/stb.adb:14 + 0x00401335: main at d:/stb/b~stb.adb:197 + 0x004011c4: ?? at crtexe.c:? + 0x004011f1: ?? at crtexe.c:? + 0x77e892a4: ?? ??:0 - 00401373 in stb.p1 at d:/stb/stb.adb:5 - 0040138B in stb.p2 at d:/stb/stb.adb:10 - 0040139C in stb at d:/stb/stb.adb:14 - 00401335 in main at d:/stb/b~stb.adb:104 - 004011C4 in <__mingw_CRTStartup> at /build/.../crt1.c:200 - 004011F1 in <mainCRTStartup> at /build/.../crt1.c:222 -From this traceback we can see that the exception was raised in -:file:`stb.adb` at line 5, which was reached from a procedure call in -:file:`stb.adb` at line 10, and so on. The :file:`b~std.adb` is the binder file, -which contains the call to the main program. -:ref:`Running_gnatbind`. The remaining entries are assorted runtime routines, -and the output will vary from platform to platform. +From this traceback we can see that the exception was raised in :file:`stb.adb` +at line 5, which was reached from a procedure call in :file:`stb.adb` at line +10, and so on. The :file:`b~std.adb` is the binder file, which contains the +call to the main program. :ref:`Running_gnatbind`. The remaining entries are +assorted runtime routines and the output will vary from platform to platform. It is also possible to use ``GDB`` with these traceback addresses to debug the program. For example, we can break at a given code location, as reported -in the stack traceback: - - :: +in the stack traceback:: $ gdb -nw stb -Furthermore, this feature is not implemented inside Windows DLL. Only -the non-symbolic traceback is reported in this case. - - :: - (gdb) break *0x401373 Breakpoint 1 at 0x401373: file stb.adb, line 5. -It is important to note that the stack traceback addresses -do not change when debug information is included. This is particularly useful -because it makes it possible to release software without debug information (to -minimize object size), get a field report that includes a stack traceback -whenever an internal bug occurs, and then be able to retrieve the sequence -of calls with the same program compiled with debug information. +It is important to note that the stack traceback addresses do not change when +debug information is included. This is particularly useful because it makes it +possible to release software without debug information (to minimize object +size), get a field report that includes a stack traceback whenever an internal +bug occurs, and then be able to retrieve the sequence of calls with the same +program compiled with debug information. + +However the ``addr2line`` tool does not work with Position-Independent Code +(PIC), the historical example being Windows DLLs, which nowadays encompasses +Position-Independent Executables (PIE) on recent Windows versions. + +In order to translate addresses into the source lines with Position-Independent +Executables on recent Windows versions, in other words without using the switch +:switch:`-no-pie` during linking, you need to use the ``gnatsymbolize`` tool +with :switch:`--load` instead of the ``addr2line`` tool. The main difference +is that you need to copy the Load Address output in the traceback ahead of the +sequence of addresses. And the default mode of ``gnatsymbolize`` is equivalent +to that of ``addr2line`` with the above switches, so none of them is needed:: + + $ gnatmake stb -g -bargs -E + $ stb + + Execution of stb terminated by unhandled exception + raised CONSTRAINT_ERROR : stb.adb:5 explicit raise + Load address: 0x400000 + Call stack traceback locations: + 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 + + $ gnatsymbolize --load stb 0x400000 0x401373 0x40138b 0x40139c 0x401335 + 0x4011c4 0x4011f1 0x77e892a4 + + 0x00401373 Stb.P1 at stb.adb:5 + 0x0040138B Stb.P2 at stb.adb:10 + 0x0040139C Stb at stb.adb:14 + 0x00401335 Main at b~stb.adb:197 + 0x004011c4 __tmainCRTStartup at ??? + 0x004011f1 mainCRTStartup at ??? + 0x77e892a4 ??? at ??? .. rubric:: Tracebacks From Exception Occurrences @@ -914,25 +932,24 @@ This program will output: $ stb - Exception name: CONSTRAINT_ERROR - Message: stb.adb:12 + raised CONSTRAINT_ERROR : stb.adb:12 range check failed + Load address: 0x400000 Call stack traceback locations: 0x4015e4 0x401633 0x401644 0x401461 0x4011c4 0x4011f1 0x77e892a4 .. rubric:: Tracebacks From Anywhere in a Program -It is also possible to retrieve a stack traceback from anywhere in a -program. For this you need to -use the ``GNAT.Traceback`` API. This package includes a procedure called -``Call_Chain`` that computes a complete stack traceback, as well as useful -display procedures described below. It is not necessary to use the -:switch:`-E` ``gnatbind`` option in this case, because the stack traceback mechanism -is invoked explicitly. +It is also possible to retrieve a stack traceback from anywhere in a program. +For this you need to use the ``GNAT.Traceback`` API. This package includes a +procedure called ``Call_Chain`` that computes a complete stack traceback, as +well as useful display procedures described below. It is not necessary to use +the :switch:`-E` ``gnatbind`` option in this case, because the stack traceback +mechanism is invoked explicitly. -In the following example we compute a traceback at a specific location in -the program, and we display it using ``GNAT.Debug_Utilities.Image`` to -convert addresses to strings: +In the following example we compute a traceback at a specific location in the +program, and we display it using ``GNAT.Debug_Utilities.Image`` to convert +addresses to strings: .. code-block:: ada @@ -976,16 +993,16 @@ convert addresses to strings: :: - $ gnatmake -g stb + $ gnatmake stb -g $ stb In STB.P1 : 16#0040_F1E4# 16#0040_14F2# 16#0040_170B# 16#0040_171C# 16#0040_1461# 16#0040_11C4# 16#0040_11F1# 16#77E8_92A4# -You can then get further information by invoking the ``addr2line`` -tool as described earlier (note that the hexadecimal addresses -need to be specified in C format, with a leading '0x'). +You can then get further information by invoking the ``addr2line`` tool or +the ``gnatsymbolize`` tool as described earlier (note that the hexadecimal +addresses need to be specified in C format, with a leading '0x'). .. index:: traceback, symbolic @@ -3716,12 +3733,13 @@ execution of this erroneous program: allocation and deallocation routines. This is done by linking with the :file:`libgmem.a` library. For correct symbolic backtrace information, the user program should also both be compiled with debugging options - (see :ref:`Switches_for_gcc`) and be linked at a fixed position. For - example to build :file:`my_program` with ``gnatmake``: + (see :ref:`Switches_for_gcc`) and be linked at a fixed position with + :switch:`-no-pie`. For example to build :file:`my_program` with + ``gnatmake``: :: - $ gnatmake -g my_program -largs -lgmem -no-pie + $ gnatmake my_program -g -largs -lgmem -no-pie As library :file:`libgmem.a` contains an alternate body for package ``System.Memory``, :file:`s-memory.adb` should not be compiled and linked diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index 27531f4..b7c9bdc 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -2081,7 +2081,7 @@ package body Einfo.Utils is -------------------- function Number_Entries (Id : E) return Nat is - N : Int; + N : Nat; Ent : Entity_Id; begin diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 4493f0f..1857055 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -5734,7 +5734,8 @@ package body Exp_Aggr is procedure Check_Bounds (Aggr_Bounds_Node, Index_Bounds_Node : Node_Id); -- Checks that the bounds of Aggr_Bounds are within the bounds defined - -- by Index_Bounds. + -- by Index_Bounds. For null array aggregate (Ada 2022) check that the + -- aggregate bounds define a null range. procedure Check_Same_Aggr_Bounds (Sub_Aggr : Node_Id; Dim : Pos); -- Checks that in a multidimensional array aggregate all subaggregates @@ -5850,6 +5851,22 @@ package body Exp_Aggr is Cond : Node_Id := Empty; begin + -- For a null array aggregate check that high bound (i.e., low + -- bound predecessor) exists. Fail if low bound is low bound of + -- base subtype (in all cases, including modular). + + if Is_Null_Aggregate (N) then + Insert_Action (N, + Make_Raise_Constraint_Error (Loc, + Condition => + Make_Op_Eq (Loc, + New_Copy_Tree (Aggr_Bounds.First), + New_Copy_Tree + (Type_Low_Bound (Base_Type (Etype (Ind_Bounds.First))))), + Reason => CE_Range_Check_Failed)); + return; + end if; + -- Generate the following test: -- [constraint_error when @@ -6430,7 +6447,7 @@ package body Exp_Aggr is Left_Opnd => New_Occurrence_Of (Size_Id, Loc), Right_Opnd => Make_Integer_Literal (Loc, 1))); - One_Loop := Make_Loop_Statement (Loc, + One_Loop := Make_Implicit_Loop_Statement (N, Iteration_Scheme => Make_Iteration_Scheme (Loc, Iterator_Specification => New_Copy_Tree (Iter)), @@ -6536,7 +6553,7 @@ package body Exp_Aggr is Prefix => New_Occurrence_Of (TmpE, Loc), Expressions => New_List (New_Occurrence_Of (Index_Id, Loc))), - Expression => New_Copy_Tree (Expression (Assoc))); + Expression => Copy_Separate_Tree (Expression (Assoc))); -- Advance index position for insertion. @@ -6562,7 +6579,7 @@ package body Exp_Aggr is Attribute_Name => Name_Last)), Then_Statements => New_List (Incr)); - One_Loop := Make_Loop_Statement (Loc, + One_Loop := Make_Implicit_Loop_Statement (N, Iteration_Scheme => Make_Iteration_Scheme (Loc, Iterator_Specification => Copy_Separate_Tree (Iter)), @@ -7500,11 +7517,11 @@ package body Exp_Aggr is -- Iterated_Component_Association. - Loop_Id := - Make_Defining_Identifier (Loc, - Chars => Chars (Defining_Identifier (Comp))); - if Present (Iterator_Specification (Comp)) then + Loop_Id := + Make_Defining_Identifier (Loc, + Chars => Chars (Defining_Identifier + (Iterator_Specification (Comp)))); L_Iteration_Scheme := Make_Iteration_Scheme (Loc, Iterator_Specification => Iterator_Specification (Comp)); @@ -7513,6 +7530,9 @@ package body Exp_Aggr is -- Loop_Parameter_Specification is parsed with a choice list. -- where the range is the first (and only) choice. + Loop_Id := + Make_Defining_Identifier (Loc, + Chars => Chars (Defining_Identifier (Comp))); L_Range := Relocate_Node (First (Discrete_Choices (Comp))); L_Iteration_Scheme := @@ -7997,7 +8017,7 @@ package body Exp_Aggr is end if; return - Make_Loop_Statement (Loc, + Make_Implicit_Loop_Statement (C, Iteration_Scheme => Make_Iteration_Scheme (Sl, Loop_Parameter_Specification => diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index ad75453..52d47d9 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -5667,33 +5667,35 @@ package body Exp_Attr is -- which is illegal, because of the lack of aliasing. when Attribute_Priority => Priority : declare - Call : Node_Id; - Conctyp : Entity_Id; - New_Itype : Entity_Id; - Object_Parm : Node_Id; - Subprg : Entity_Id; - RT_Subprg_Name : Node_Id; + Call : Node_Id; + New_Itype : Entity_Id; + Object_Parm : Node_Id; + Prottyp : Entity_Id; + RT_Subprg : RE_Id; + Subprg : Entity_Id; begin - -- Look for the enclosing concurrent type + -- Look for the enclosing protected type - Conctyp := Current_Scope; - while not Is_Concurrent_Type (Conctyp) loop - Conctyp := Scope (Conctyp); + Prottyp := Current_Scope; + while not Is_Protected_Type (Prottyp) loop + Prottyp := Scope (Prottyp); end loop; - pragma Assert (Is_Protected_Type (Conctyp)); + pragma Assert (Is_Protected_Type (Prottyp)); -- Generate the actual of the call Subprg := Current_Scope; - while not Present (Protected_Body_Subprogram (Subprg)) loop + while not (Is_Subprogram_Or_Entry (Subprg) + and then Present (Protected_Body_Subprogram (Subprg))) + loop Subprg := Scope (Subprg); end loop; -- Use of 'Priority inside protected entries and barriers (in both -- cases the type of the first formal of their expanded subprogram - -- is Address) + -- is Address). if Etype (First_Entity (Protected_Body_Subprogram (Subprg))) = RTE (RE_Address) @@ -5708,7 +5710,7 @@ package body Exp_Attr is New_Itype := Create_Itype (E_Access_Type, N); Set_Etype (New_Itype, New_Itype); Set_Directly_Designated_Type (New_Itype, - Corresponding_Record_Type (Conctyp)); + Corresponding_Record_Type (Prottyp)); Freeze_Itype (New_Itype, N); -- Generate: @@ -5743,15 +5745,16 @@ package body Exp_Attr is -- Select the appropriate run-time subprogram - if Number_Entries (Conctyp) = 0 then - RT_Subprg_Name := New_Occurrence_Of (RTE (RE_Get_Ceiling), Loc); + if Has_Entries (Prottyp) then + RT_Subprg := RO_PE_Get_Ceiling; else - RT_Subprg_Name := New_Occurrence_Of (RTE (RO_PE_Get_Ceiling), Loc); + RT_Subprg := RE_Get_Ceiling; end if; Call := Make_Function_Call (Loc, - Name => RT_Subprg_Name, + Name => + New_Occurrence_Of (RTE (RT_Subprg), Loc), Parameter_Associations => New_List (Object_Parm)); Rewrite (N, Call); diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index 38552ef..0d82691 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -7850,6 +7850,7 @@ package body Exp_Ch3 is and then Present (DIC_Procedure (Typ)) and then not Has_Null_Body (DIC_Procedure (Typ)) and then not Has_Init_Expression (N) + and then No (Expr) and then not Is_Imported (Def_Id) then declare @@ -9182,9 +9183,12 @@ package body Exp_Ch3 is -- the runtime verification of all invariants that pertain to the type. -- This includes invariants on the partial and full view, inherited -- class-wide invariants from parent types or interfaces, and invariants - -- on array elements or record components. + -- on array elements or record components. But skip internal types. - if Is_Interface (Def_Id) then + if Is_Itype (Def_Id) then + null; + + elsif Is_Interface (Def_Id) then -- Interfaces are treated as the partial view of a private type in -- order to achieve uniformity with the general case. As a result, an diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 9a2a110..2e14c97 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -2392,11 +2392,10 @@ package body Exp_Ch5 is if Ada_Version >= Ada_2005 then declare - Call : Node_Id; - Conctyp : Entity_Id; - Ent : Entity_Id; - Subprg : Entity_Id; - RT_Subprg_Name : Node_Id; + Call : Node_Id; + Ent : Entity_Id; + Prottyp : Entity_Id; + RT_Subprg : RE_Id; begin -- Handle chains of renamings @@ -2416,35 +2415,27 @@ package body Exp_Ch5 is if Is_Expanded_Priority_Attribute (Ent) then - -- Look for the enclosing concurrent type + -- Look for the enclosing protected type - Conctyp := Current_Scope; - while not Is_Concurrent_Type (Conctyp) loop - Conctyp := Scope (Conctyp); + Prottyp := Current_Scope; + while not Is_Protected_Type (Prottyp) loop + Prottyp := Scope (Prottyp); end loop; - pragma Assert (Is_Protected_Type (Conctyp)); - - -- Generate the first actual of the call - - Subprg := Current_Scope; - while not Present (Protected_Body_Subprogram (Subprg)) loop - Subprg := Scope (Subprg); - end loop; + pragma Assert (Is_Protected_Type (Prottyp)); -- Select the appropriate run-time call - if Number_Entries (Conctyp) = 0 then - RT_Subprg_Name := - New_Occurrence_Of (RTE (RE_Set_Ceiling), Loc); + if Has_Entries (Prottyp) then + RT_Subprg := RO_PE_Set_Ceiling; else - RT_Subprg_Name := - New_Occurrence_Of (RTE (RO_PE_Set_Ceiling), Loc); + RT_Subprg := RE_Set_Ceiling; end if; Call := Make_Procedure_Call_Statement (Loc, - Name => RT_Subprg_Name, + Name => + New_Occurrence_Of (RTE (RT_Subprg), Loc), Parameter_Associations => New_List ( New_Copy_Tree (First (Parameter_Associations (Ent))), Relocate_Node (Expression (N)))); diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index fad130d..fe3bb5b 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -6632,7 +6632,7 @@ package body Exp_Ch6 is begin if not Exp_Is_Function_Call - and then Has_Discriminants (Ubt) + and then Has_Defaulted_Discriminants (Ubt) and then not Is_Constrained (Ubt) and then not Has_Unchecked_Union (Ubt) then diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 3286bf6..0bc22a4 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -2042,7 +2042,7 @@ package body Exp_Util is elsif Is_Underlying_Full_View (Work_Typ) then return; - -- Use the first subtype when dealing with various base types + -- Use the first subtype when dealing with implicit base types elsif Is_Itype (Work_Typ) then Work_Typ := First_Subtype (Work_Typ); @@ -5187,19 +5187,6 @@ package body Exp_Util is end if; end Ensure_Defined; - -------------------- - -- Entry_Names_OK -- - -------------------- - - function Entry_Names_OK return Boolean is - begin - return - not Restricted_Profile - and then not Global_Discard_Names - and then not Restriction_Active (No_Implicit_Heap_Allocations) - and then not Restriction_Active (No_Local_Allocators); - end Entry_Names_OK; - ------------------- -- Evaluate_Name -- ------------------- @@ -5732,14 +5719,17 @@ package body Exp_Util is then if Is_Itype (Exp_Typ) - -- If Exp_Typ was created for a previous declaration whose nominal - -- subtype is unconstrained, and that declaration is aliased, - -- we need to generate a new subtype, because otherwise the - -- Is_Constr_Subt_For_U_Nominal flag will be set on the wrong - -- subtype, causing failure to detect non-statically-matching - -- subtypes on 'Access of the previously-declared object. - - and then not Is_Constr_Subt_For_UN_Aliased (Exp_Typ) + -- When this is for an object declaration, the caller may want to + -- set Is_Constr_Subt_For_U_Nominal on the subtype, so we must make + -- sure that either the subtype has been built for the expression, + -- typically for an aggregate, or the flag is already set on it; + -- otherwise it could end up being set on the nominal constrained + -- subtype of an object and thus later cause the failure to detect + -- non-statically-matching subtypes on 'Access of this object. + + and then (Nkind (N) /= N_Object_Declaration + or else Nkind (Original_Node (Exp)) = N_Aggregate + or else Is_Constr_Subt_For_U_Nominal (Exp_Typ)) then -- Within an initialization procedure, a selected component -- denotes a component of the enclosing record, and it appears as diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index d854672..a21fb8b 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -509,11 +509,6 @@ package Exp_Util is -- used to ensure that an Itype is properly defined outside a conditional -- construct when it is referenced in more than one branch. - function Entry_Names_OK return Boolean; - -- Determine whether it is appropriate to dynamically allocate strings - -- which represent entry [family member] names. These strings are created - -- by the compiler and used by GDB. - procedure Evaluate_Name (Nam : Node_Id); -- Remove all side effects from a name which appears as part of an object -- renaming declaration. Similarly to Force_Evaluation, it removes the diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 382e5b4..52858e2 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -6366,9 +6366,7 @@ package body Freeze is end; end if; - if Has_Delayed_Aspects (E) - or else May_Inherit_Delayed_Rep_Aspects (E) - then + if Has_Delayed_Aspects (E) then Analyze_Aspects_At_Freeze_Point (E); end if; @@ -6799,18 +6797,25 @@ package body Freeze is -- A subtype inherits all the type-related representation aspects -- from its parents (RM 13.1(8)). + if May_Inherit_Delayed_Rep_Aspects (E) then + Inherit_Delayed_Rep_Aspects (E); + end if; + Inherit_Aspects_At_Freeze_Point (E); -- For a derived type, freeze its parent type first (RM 13.14(15)) elsif Is_Derived_Type (E) then Freeze_And_Append (Etype (E), N, Result); - Freeze_And_Append (First_Subtype (Etype (E)), N, Result); -- A derived type inherits each type-related representation aspect -- of its parent type that was directly specified before the -- declaration of the derived type (RM 13.1(15)). + if May_Inherit_Delayed_Rep_Aspects (E) then + Inherit_Delayed_Rep_Aspects (E); + end if; + Inherit_Aspects_At_Freeze_Point (E); end if; @@ -9089,6 +9094,11 @@ package body Freeze is Set_Has_Delayed_Aspects (Ftyp, False); end if; + if May_Inherit_Delayed_Rep_Aspects (Ftyp) then + Inherit_Delayed_Rep_Aspects (Ftyp); + Set_May_Inherit_Delayed_Rep_Aspects (Ftyp, False); + end if; + -- Inherit the Small value from the first subtype in any case if Typ /= Ftyp then @@ -9653,9 +9663,7 @@ package body Freeze is Set_Has_Delayed_Freeze (T); L := Freeze_Entity (T, N); - if Is_Non_Empty_List (L) then - Insert_Actions (N, L); - end if; + Insert_Actions (N, L); end Freeze_Itype; -------------------------- diff --git a/gcc/ada/gnat-style.texi b/gcc/ada/gnat-style.texi index cbc11ac..f3b1c29 100644 --- a/gcc/ada/gnat-style.texi +++ b/gcc/ada/gnat-style.texi @@ -3,7 +3,7 @@ @setfilename gnat-style.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 4.3.1.@* +@*Generated by Sphinx 5.1.1.@* @end ifinfo @settitle GNAT Coding Style A Guide for GNAT Developers @defindex ge @@ -15,13 +15,11 @@ * gnat-style: (gnat-style.info). gnat-style @end direntry -@definfoenclose strong,`,' -@definfoenclose emph,`,' @c %**end of header @copying @quotation -GNAT Coding Style: A Guide for GNAT Developers , Jan 03, 2022 +GNAT Coding Style: A Guide for GNAT Developers , Aug 25, 2022 AdaCore @@ -255,7 +253,7 @@ When declarations are commented with ‘hanging’ comments, i.e. comments after the declaration, there is no blank line before the comment, and if it is absolutely necessary to have blank lines within the comments, e.g. to make paragraph separations within a single comment, -these blank lines @emph{do} have a @code{--} (unlike the +these blank lines `do' have a @code{--} (unlike the normal rule, which is to use entirely blank lines for separating comment paragraphs). The comment starts at same level of indentation as code it is commenting. @@ -304,12 +302,12 @@ Other_Id := 6; -- Second comment @end example @item -Short comments that fit on a single line are @emph{not} ended with a +Short comments that fit on a single line are `not' ended with a period. Comments taking more than a line are punctuated in the normal manner. @item -Comments should focus on @emph{why} instead of @emph{what}. +Comments should focus on `why' instead of `what'. Descriptions of what subprograms do go with the specification. @item @@ -319,7 +317,7 @@ depend on the names of things. The names are supplementary, not sufficient, as comments. @item -@emph{Do not} put two spaces after periods in comments. +`Do not' put two spaces after periods in comments. @end itemize @node Declarations and Types,Expressions and Names,Lexical Elements,Top @@ -958,7 +956,7 @@ Copyright 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -@strong{Preamble} +`Preamble' The purpose of this License is to make a manual, textbook, or other functional and useful document “free†in the sense of freedom: to @@ -981,23 +979,23 @@ it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. -@strong{1. APPLICABILITY AND DEFINITIONS} +`1. APPLICABILITY AND DEFINITIONS' This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that -work under the conditions stated herein. The @strong{Document}, below, +work under the conditions stated herein. The `Document', below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as “@strong{you}â€. You accept the license if you +licensee, and is addressed as “`you'â€. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. -A “@strong{Modified Version}†of the Document means any work containing the +A “`Modified Version'†of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. -A “@strong{Secondary Section}†is a named appendix or a front-matter section of +A “`Secondary Section'†is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly @@ -1008,7 +1006,7 @@ connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. -The “@strong{Invariant Sections}†are certain Secondary Sections whose titles +The “`Invariant Sections'†are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not @@ -1016,12 +1014,12 @@ allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. -The “@strong{Cover Texts}†are certain short passages of text that are listed, +The “`Cover Texts'†are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. -A “@strong{Transparent}†copy of the Document means a machine-readable copy, +A “`Transparent'†copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of @@ -1032,7 +1030,7 @@ to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount -of text. A copy that is not “Transparent†is called @strong{Opaque}. +of text. A copy that is not “Transparent†is called `Opaque'. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML @@ -1045,22 +1043,22 @@ processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. -The “@strong{Title Page}†means, for a printed book, the title page itself, +The “`Title Page'†means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page†means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. -The “@strong{publisher}†means any person or entity that distributes +The “`publisher'†means any person or entity that distributes copies of the Document to the public. -A section “@strong{Entitled XYZ}†means a named subunit of the Document whose +A section “`Entitled XYZ'†means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as “@strong{Acknowledgements}â€, -“@strong{Dedications}â€, “@strong{Endorsements}â€, or “@strong{History}â€.) -To “@strong{Preserve the Title}†+specific section name mentioned below, such as “`Acknowledgements'â€, +“`Dedications'â€, “`Endorsements'â€, or “`History'â€.) +To “`Preserve the Title'†of such a section when you modify the Document means that it remains a section “Entitled XYZ†according to this definition. @@ -1071,7 +1069,7 @@ License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. -@strong{2. VERBATIM COPYING} +`2. VERBATIM COPYING' You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the @@ -1086,7 +1084,7 @@ number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. -@strong{3. COPYING IN QUANTITY} +`3. COPYING IN QUANTITY' If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the @@ -1123,7 +1121,7 @@ It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. -@strong{4. MODIFICATIONS} +`4. MODIFICATIONS' You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release @@ -1240,7 +1238,7 @@ The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. -@strong{5. COMBINING DOCUMENTS} +`5. COMBINING DOCUMENTS' You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified @@ -1264,7 +1262,7 @@ in the various original documents, forming one section Entitled and any sections Entitled “Dedicationsâ€. You must delete all sections Entitled “Endorsementsâ€. -@strong{6. COLLECTIONS OF DOCUMENTS} +`6. COLLECTIONS OF DOCUMENTS' You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this @@ -1277,7 +1275,7 @@ it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. -@strong{7. AGGREGATION WITH INDEPENDENT WORKS} +`7. AGGREGATION WITH INDEPENDENT WORKS' A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or @@ -1296,7 +1294,7 @@ electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. -@strong{8. TRANSLATION} +`8. TRANSLATION' Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. @@ -1316,7 +1314,7 @@ If a section in the Document is Entitled “Acknowledgementsâ€, its Title (section 1) will typically require changing the actual title. -@strong{9. TERMINATION} +`9. TERMINATION' You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt @@ -1343,7 +1341,7 @@ this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. -@strong{10. FUTURE REVISIONS OF THIS LICENSE} +`10. FUTURE REVISIONS OF THIS LICENSE' The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new @@ -1364,7 +1362,7 @@ License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. -@strong{11. RELICENSING} +`11. RELICENSING' “Massive Multiauthor Collaboration Site†(or “MMC Siteâ€) means any World Wide Web server that publishes copyrightable works and also @@ -1393,7 +1391,7 @@ The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. -@strong{ADDENDUM: How to use this License for your documents} +`ADDENDUM: How to use this License for your documents' To use this License in a document you have written, include a copy of the License in the document and put the following copyright and diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index 1ffc146..fe2f434 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -3,7 +3,7 @@ @setfilename gnat_rm.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 4.3.1.@* +@*Generated by Sphinx 5.1.1.@* @end ifinfo @settitle GNAT Reference Manual @defindex ge @@ -15,13 +15,11 @@ * gnat_rm: (gnat_rm.info). gnat_rm @end direntry -@definfoenclose strong,`,' -@definfoenclose emph,`,' @c %**end of header @copying @quotation -GNAT Reference Manual , Jul 11, 2022 +GNAT Reference Manual , Aug 25, 2022 AdaCore @@ -48,7 +46,7 @@ Copyright @copyright{} 2008-2022, Free Software Foundation @c %**start of body @anchor{gnat_rm doc}@anchor{0} -@emph{GNAT, The GNU Ada Development Environment} +`GNAT, The GNU Ada Development Environment' @include gcc-common.texi @@ -943,7 +941,7 @@ invoked in Ada 83 compatibility mode. By default, GNAT assumes Ada 2012, but you can override with a compiler switch to explicitly specify the language version. -(Please refer to the @emph{GNAT User’s Guide} for details on these switches.) +(Please refer to the `GNAT User’s Guide' for details on these switches.) Throughout this manual, references to ‘Ada’ without a year suffix apply to all the Ada versions of the language. @@ -1109,7 +1107,7 @@ and @code{classes}. @code{Variables} @item -@emph{Emphasis} +`Emphasis' @item [optional information or parameters] @@ -1784,7 +1782,7 @@ type of the expression is either @code{Standard.Boolean}, or any type derived from this standard type. Assert checks can be either checked or ignored. By default they are ignored. -They will be checked if either the command line switch @emph{-gnata} is +They will be checked if either the command line switch `-gnata' is used, or if an @code{Assertion_Policy} or @code{Check_Policy} pragma is used to enable @code{Assert_Checks}. @@ -1906,10 +1904,10 @@ If the policy is @code{CHECK}, then assertions are enabled, i.e. the corresponding pragma or aspect is activated. If the policy is @code{IGNORE}, then assertions are ignored, i.e. the corresponding pragma or aspect is deactivated. -This pragma overrides the effect of the @emph{-gnata} switch on the +This pragma overrides the effect of the `-gnata' switch on the command line. If the policy is @code{SUPPRESSIBLE}, then assertions are enabled by default, -however, if the @emph{-gnatp} switch is specified all assertions are ignored. +however, if the `-gnatp' switch is specified all assertions are ignored. The implementation defined policy @code{DISABLE} is like @code{IGNORE} except that it completely disables semantic @@ -2143,7 +2141,7 @@ be independently controlled. The identifier @code{Assertion} is special, it refers to the normal set of pragma @code{Assert} statements. Checks introduced by this pragma are normally deactivated by default. They can -be activated either by the command line option @emph{-gnata}, which turns on +be activated either by the command line option `-gnata', which turns on all checks, or individually controlled using pragma @code{Check_Policy}. The identifiers @code{Assertions} and @code{Statement_Assertions} are not @@ -2166,7 +2164,7 @@ pragma Check_Float_Overflow; In Ada, the predefined floating-point types (@code{Short_Float}, @code{Float}, @code{Long_Float}, @code{Long_Long_Float}) are -defined to be @emph{unconstrained}. This means that even though each +defined to be `unconstrained'. This means that even though each has a well-defined base range, an operation that delivers a result outside this base range is not required to raise an exception. This implementation permission accommodates the notion @@ -2205,7 +2203,7 @@ will be generated. The @code{Constraint_Error} exception is raised if the result is out of range. This mode can also be set by use of the compiler -switch @emph{-gnateF}. +switch `-gnateF'. @node Pragma Check_Name,Pragma Check_Policy,Pragma Check_Float_Overflow,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-check-name}@anchor{37} @@ -2315,7 +2313,7 @@ is given, then subsequent @code{Check} pragmas whose first argument is also The check policy is @code{OFF} to turn off corresponding checks, and @code{ON} to turn on corresponding checks. The default for a set of checks for which no @code{Check_Policy} is given is @code{OFF} unless the compiler switch -@emph{-gnata} is given, which turns on all checks by default. +`-gnata' is given, which turns on all checks by default. The check policy settings @code{CHECK} and @code{IGNORE} are recognized as synonyms for @code{ON} and @code{OFF}. These synonyms are provided for @@ -2414,7 +2412,7 @@ pragma Compile_Time_Warning @end example Same as pragma Compile_Time_Error, except a warning is issued instead -of an error message. If switch @emph{-gnatw_C} is used, a warning is only issued +of an error message. If switch `-gnatw_C' is used, a warning is only issued if the value of the expression is known to be True at compile time, not when the value of the expression is not known at compile time. Note that if this pragma is used in a package that @@ -2427,7 +2425,7 @@ of formal parameters are tested, and warnings given appropriately. Another use with a first parameter of True is to warn a client about use of a package, for example that it is not fully implemented. -In previous versions of the compiler, combining @emph{-gnatwe} with +In previous versions of the compiler, combining `-gnatwe' with Compile_Time_Warning resulted in a fatal error. Now the compiler always emits a warning. You can use @ref{3b,,Pragma Compile_Time_Error} to force the generation of an error. @@ -2507,7 +2505,7 @@ The meaning of the @code{Form} argument is as follows: @table @asis -@item @emph{Component_Size} +@item `Component_Size' Aligns scalar components and subcomponents of the array or record type on boundaries appropriate to their inherent size (naturally @@ -2519,7 +2517,7 @@ machines except the VAX. @geindex Component_Size_4 (in pragma Component_Alignment) -@item @emph{Component_Size_4} +@item `Component_Size_4' Naturally aligns components with a size of four or fewer bytes. Components that are larger than 4 bytes are placed on the next @@ -2527,7 +2525,7 @@ bytes. Components that are larger than 4 bytes are placed on the next @geindex Storage_Unit (in pragma Component_Alignment) -@item @emph{Storage_Unit} +@item `Storage_Unit' Specifies that array or record components are byte aligned, i.e., aligned on boundaries determined by the value of the constant @@ -2535,7 +2533,7 @@ aligned on boundaries determined by the value of the constant @geindex Default (in pragma Component_Alignment) -@item @emph{Default} +@item `Default' Specifies that array or record components are aligned on default boundaries, appropriate to the underlying hardware or operating system or @@ -2757,16 +2755,16 @@ must be of one of the following forms: @itemize * @item -@strong{function} @code{Fname} @strong{return} T` +`function' @code{Fname} `return' T` @item -@strong{function} @code{Fname} @strong{return} T’Class +`function' @code{Fname} `return' T’Class @item -@strong{function} @code{Fname} (…) @strong{return} T` +`function' @code{Fname} (…) `return' T` @item -@strong{function} @code{Fname} (…) @strong{return} T’Class +`function' @code{Fname} (…) `return' T’Class @end itemize where @code{T} is a limited record type imported from C++ with pragma @@ -2890,7 +2888,7 @@ semantics of the pragma is exactly equivalent to the procedure call statement corresponding to the argument with a terminating semicolon. Pragmas are permitted in sequences of declarations, so you can use pragma @code{Debug} to intersperse calls to debug procedures in the middle of declarations. Debug -pragmas can be enabled either by use of the command line switch @emph{-gnata} +pragmas can be enabled either by use of the command line switch `-gnata' or by use of the pragma @code{Check_Policy} with a first argument of @code{Debug}. @@ -2968,8 +2966,8 @@ package DSSO1 is end DSSO1; @end example -In this example record types with names starting with @emph{L} have @cite{Low_Order_First} scalar -storage order, and record types with names starting with @emph{H} have @code{High_Order_First}. +In this example record types with names starting with `L' have @cite{Low_Order_First} scalar +storage order, and record types with names starting with `H' have @code{High_Order_First}. Note that in the case of @code{H4a}, the order is not inherited from the parent type. Only an explicitly set @code{Scalar_Storage_Order} gets inherited on type derivation. @@ -3134,8 +3132,8 @@ pragma Elaboration_Checks (Dynamic | Static); This is a configuration pragma which specifies the elaboration model to be used during compilation. For more information on the elaboration models of -GNAT, consult the chapter on elaboration order handling in the @emph{GNAT User’s -Guide}. +GNAT, consult the chapter on elaboration order handling in the `GNAT User’s +Guide'. The pragma may appear in the following contexts: @@ -3582,14 +3580,14 @@ the Ada RM. However, other implementations, notably the DEC Ada 83 implementation, provide many extensions to package @code{System}. For each such implementation accommodated by this pragma, GNAT provides a -package @code{Aux_@emph{xxx}}, e.g., @code{Aux_DEC} for the DEC Ada 83 +package @code{Aux_@var{xxx}}, e.g., @code{Aux_DEC} for the DEC Ada 83 implementation, which provides the required additional definitions. You can use this package in two ways. You can @code{with} it in the normal way and access entities either by selection or using a @code{use} clause. In this case no special processing is required. However, if existing code contains references such as -@code{System.@emph{xxx}} where @emph{xxx} is an entity in the extended +@code{System.@var{xxx}} where `xxx' is an entity in the extended definitions provided in package @code{System}, you may use this pragma to extend visibility in @code{System} in a non-standard way that provides greater compatibility with the existing code. Pragma @@ -3597,8 +3595,8 @@ provides greater compatibility with the existing code. Pragma the name of the package containing the extended definition (e.g., @code{Aux_DEC} for the DEC Ada case). A unit compiled under control of this pragma will be processed using special visibility -processing that looks in package @code{System.Aux_@emph{xxx}} where -@code{Aux_@emph{xxx}} is the pragma argument for any entity referenced in +processing that looks in package @code{System.Aux_@var{xxx}} where +@code{Aux_@var{xxx}} is the pragma argument for any entity referenced in package @code{System}, but not found in package @code{System}. You can use this pragma either to access a predefined @code{System} @@ -3606,7 +3604,7 @@ extension supplied with the compiler, for example @code{Aux_DEC} or you can construct your own extension unit following the above definition. Note that such a package is a child of @code{System} and thus is considered part of the implementation. -To compile it you will have to use the @emph{-gnatg} switch +To compile it you will have to use the `-gnatg' switch for compiling System units, as explained in the GNAT User’s Guide. @@ -3627,7 +3625,7 @@ pragma Extensions_Allowed (On | Off); This configuration pragma enables or disables the implementation extension mode (the use of Off as a parameter cancels the effect -of the @emph{-gnatX} command switch). +of the `-gnatX' command switch). In extension mode, the latest version of the Ada language is implemented (currently Ada 2022), and in addition a number @@ -4033,7 +4031,7 @@ following operations are affected: @table @asis -@item @emph{Complex Multiplication} +@item `Complex Multiplication' The normal simple formula for complex multiplication can result in intermediate overflows for numbers near the end of the range. The Ada standard requires that @@ -4657,7 +4655,7 @@ program. Note that pragma @code{Initialize_Scalars} is particularly useful in conjunction with the enhanced validity checking that is now provided in GNAT, which checks for invalid values under more conditions. Using this feature (see description -of the @emph{-gnatV} flag in the GNAT User’s Guide) in conjunction with pragma +of the `-gnatV' flag in the GNAT User’s Guide) in conjunction with pragma @code{Initialize_Scalars} provides a powerful new tool to assist in the detection of problems caused by uninitialized variables. @@ -4708,7 +4706,7 @@ pragma Inline_Always (NAME [, NAME]); Similar to pragma @code{Inline} except that inlining is unconditional. Inline_Always instructs the compiler to inline every direct call to the subprogram or else to emit a compilation error, independently of any -option, in particular @emph{-gnatn} or @emph{-gnatN} or the optimization level. +option, in particular `-gnatn' or `-gnatN' or the optimization level. It is an error to take the address or access of @code{NAME}. It is also an error to apply this pragma to a primitive operation of a tagged type. Thanks to such restrictions, the compiler is allowed to remove the out-of-line body of @code{NAME}. @@ -5367,7 +5365,7 @@ unrolling, but there is no guarantee that the loop will be vectorized. These hints do not remove the need to pass the appropriate switches to the compiler in order to enable the relevant optimizations, that is to say -@emph{-funroll-loops} for unrolling and @emph{-ftree-vectorize} for +`-funroll-loops' for unrolling and `-ftree-vectorize' for vectorization. @node Pragma Loop_Variant,Pragma Machine_Attribute,Pragma Loop_Optimize,Implementation Defined Pragmas @@ -5433,10 +5431,10 @@ pragma Machine_Attribute ( Machine-dependent attributes can be specified for types and/or declarations. This pragma is semantically equivalent to -@code{__attribute__((@emph{attribute_name}))} (if @code{info} is not -specified) or @code{__attribute__((@emph{attribute_name(info})))} -or @code{__attribute__((@emph{attribute_name(info,...})))} in GNU C, -where @emph{attribute_name} is recognized by the compiler middle-end +@code{__attribute__((@var{attribute_name}))} (if @code{info} is not +specified) or @code{__attribute__((@var{attribute_name(info})))} +or @code{__attribute__((@var{attribute_name(info,...})))} in GNU C, +where `attribute_name' is recognized by the compiler middle-end or the @code{TARGET_ATTRIBUTE_TABLE} machine specific macro. Note that a string literal for the optional parameter @code{info} or the following ones is transformed by default into an identifier, @@ -5621,8 +5619,8 @@ pragma No_Inline (NAME @{, NAME@}); This pragma suppresses inlining for the callable entity or the instances of the generic subprogram designated by @code{NAME}, including inlining that results from the use of pragma @code{Inline}. This pragma is always active, -in particular it is not subject to the use of option @emph{-gnatn} or -@emph{-gnatN}. It is illegal to specify both pragma @code{No_Inline} and +in particular it is not subject to the use of option `-gnatn' or +`-gnatN'. It is illegal to specify both pragma @code{No_Inline} and pragma @code{Inline_Always} for the same @code{NAME}. @node Pragma No_Return,Pragma No_Strict_Aliasing,Pragma No_Inline,Implementation Defined Pragmas @@ -5732,28 +5730,28 @@ are as follows: @table @asis -@item @emph{Standard.Character} +@item `Standard.Character' Objects whose root type is Standard.Character are initialized to Character’Last unless the subtype range excludes NUL (in which case NUL is used). This choice will always generate an invalid value if one exists. -@item @emph{Standard.Wide_Character} +@item `Standard.Wide_Character' Objects whose root type is Standard.Wide_Character are initialized to Wide_Character’Last unless the subtype range excludes NUL (in which case NUL is used). This choice will always generate an invalid value if one exists. -@item @emph{Standard.Wide_Wide_Character} +@item `Standard.Wide_Wide_Character' Objects whose root type is Standard.Wide_Wide_Character are initialized to the invalid value 16#FFFF_FFFF# unless the subtype range excludes NUL (in which case NUL is used). This choice will always generate an invalid value if one exists. -@item @emph{Integer types} +@item `Integer types' Objects of an integer type are treated differently depending on whether negative values are present in the subtype. If no negative values are @@ -5768,26 +5766,26 @@ is in the subtype, and the largest positive number is not, in which case the largest positive value is used. This choice will always generate an invalid value if one exists. -@item @emph{Floating-Point Types} +@item `Floating-Point Types' Objects of all floating-point types are initialized to all 1-bits. For standard IEEE format, this corresponds to a NaN (not a number) which is indeed an invalid value. -@item @emph{Fixed-Point Types} +@item `Fixed-Point Types' Objects of all fixed-point types are treated as described above for integers, with the rules applying to the underlying integer value used to represent the fixed-point value. -@item @emph{Modular types} +@item `Modular types' Objects of a modular type are initialized to all one bits, except in the special case where zero is excluded from the subtype, in which case all zero bits are used. This choice will always generate an invalid value if one exists. -@item @emph{Enumeration types} +@item `Enumeration types' Objects of an enumeration type are initialized to all one-bits, i.e., to the value @code{2 ** typ'Size - 1} unless the subtype excludes the literal @@ -6001,7 +5999,7 @@ specifies a set of possible colors, and the order is unimportant. For unordered enumeration types, it is generally a good idea if clients avoid comparisons (other than equality or inequality) and -explicit ranges. (A @emph{client} is a unit where the type is referenced, +explicit ranges. (A `client' is a unit where the type is referenced, other than the unit where the type is declared, its body, and its subunits.) For example, if code buried in some client says: @@ -6044,7 +6042,7 @@ if D in Mon .. Fri then ... if D < Wed then ... @end example -The pragma @emph{Ordered} is provided to mark enumeration types that +The pragma `Ordered' is provided to mark enumeration types that are conceptually ordered, alerting the reader that clients may depend on the ordering. GNAT provides a pragma to mark enumerations as ordered rather than one to mark them as unordered, since in our experience, @@ -6056,7 +6054,7 @@ are considered to be ordered types, so each is declared with a pragma @code{Ordered} in package @code{Standard}. Normally pragma @code{Ordered} serves only as documentation and a guide for -coding standards, but GNAT provides a warning switch @emph{-gnatw.u} that +coding standards, but GNAT provides a warning switch `-gnatw.u' that requests warnings for inappropriate uses (comparisons and explicit subranges) for unordered types. If this switch is used, then any enumeration type not marked with pragma @code{Ordered} will be considered @@ -6067,7 +6065,7 @@ template can be instantiated for both cases), so we never generate warnings for the case of generic enumerated types. For additional information please refer to the description of the -@emph{-gnatw.u} switch in the GNAT User’s Guide. +`-gnatw.u' switch in the GNAT User’s Guide. @node Pragma Overflow_Mode,Pragma Overriding_Renamings,Pragma Ordered,Implementation Defined Pragmas @anchor{gnat_rm/implementation_defined_pragmas pragma-overflow-mode}@anchor{af} @@ -6298,7 +6296,7 @@ referenced in the postcondition expressions. The postconditions are collected and automatically tested just before any return (implicit or explicit) in the subprogram body. A postcondition is only recognized if postconditions are active -at the time the pragma is encountered. The compiler switch @emph{gnata} +at the time the pragma is encountered. The compiler switch `gnata' turns on all postconditions by default, and pragma @code{Check_Policy} with an identifier of @code{Postcondition} can also be used to control whether postconditions are active. @@ -7430,22 +7428,22 @@ run with various special switches as follows: @itemize * @item -@emph{Where compiler-generated run-time checks remain} +`Where compiler-generated run-time checks remain' -The switch @emph{-gnatGL} +The switch `-gnatGL' may be used to list the expanded code in pseudo-Ada form. Runtime checks show up in the listing either as explicit checks or operators marked with @{@} to indicate a check is present. @item -@emph{An identification of known exceptions at compile time} +`An identification of known exceptions at compile time' -If the program is compiled with @emph{-gnatwa}, +If the program is compiled with `-gnatwa', the compiler warning messages will indicate all cases where the compiler detects that an exception is certain to occur at run time. @item -@emph{Possible reads of uninitialized variables} +`Possible reads of uninitialized variables' The compiler warns of many such cases, but its output is incomplete. @end itemize @@ -7459,29 +7457,29 @@ possible points at which uninitialized data may be read. @itemize * @item -@emph{Where run-time support routines are implicitly invoked} +`Where run-time support routines are implicitly invoked' -In the output from @emph{-gnatGL}, +In the output from `-gnatGL', run-time calls are explicitly listed as calls to the relevant run-time routine. @item -@emph{Object code listing} +`Object code listing' -This may be obtained either by using the @emph{-S} switch, +This may be obtained either by using the `-S' switch, or the objdump utility. @item -@emph{Constructs known to be erroneous at compile time} +`Constructs known to be erroneous at compile time' -These are identified by warnings issued by the compiler (use @emph{-gnatwa}). +These are identified by warnings issued by the compiler (use `-gnatwa'). @item -@emph{Stack usage information} +`Stack usage information' Static stack usage data (maximum per-subprogram) can be obtained via the -@emph{-fstack-usage} switch to the compiler. -Dynamic stack usage data (per task) can be obtained via the @emph{-u} switch +`-fstack-usage' switch to the compiler. +Dynamic stack usage data (per task) can be obtained via the `-u' switch to gnatbind @end itemize @@ -7490,21 +7488,21 @@ to gnatbind @itemize * @item -@emph{Object code listing of entire partition} +`Object code listing of entire partition' -This can be obtained by compiling the partition with @emph{-S}, +This can be obtained by compiling the partition with `-S', or by applying objdump to all the object files that are part of the partition. @item -@emph{A description of the run-time model} +`A description of the run-time model' The full sources of the run-time are available, and the documentation of these routines describes how these run-time routines interface to the underlying operating system facilities. @item -@emph{Control and data-flow information} +`Control and data-flow information' @end itemize @@ -7810,7 +7808,7 @@ the pragma line (for use in error messages and debugging information). @code{string_literal} is a static string constant that specifies the file name to be used in error messages and debugging information. This is most notably used for the output of @code{gnatchop} -with the @emph{-r} switch, to make sure that the original unchopped +with the `-r' switch, to make sure that the original unchopped source file is the one referred to. The second argument must be a string literal, it cannot be a static @@ -8023,7 +8021,7 @@ the @code{gnat.adc} file). The form with a string literal specifies which style options are to be activated. These are additive, so they apply in addition to any previously set style check options. The codes for the options are the same as those -used in the @emph{-gnaty} switch to @emph{gcc} or @emph{gnatmake}. +used in the `-gnaty' switch to `gcc' or `gnatmake'. For example the following two methods can be used to enable layout checking: @@ -8909,7 +8907,7 @@ The form with a string literal specifies which validity options are to be activated. The validity checks are first set to include only the default reference manual settings, and then a string of letters in the string specifies the exact set of options required. The form of this string -is exactly as described for the @emph{-gnatVx} compiler switch (see the +is exactly as described for the `-gnatVx' compiler switch (see the GNAT User’s Guide for details). For example the following two methods can be used to enable validity checking for mode @code{in} and @code{in out} subprogram parameters: @@ -9033,8 +9031,8 @@ message string (it is not necessary to put an asterisk at the start and the end of the message, since this is implied). Another possibility for the static_string_EXPRESSION which works whether -or not error tags are enabled (@emph{-gnatw.d}) is to use a single -@emph{-gnatw} tag string, enclosed in brackets, +or not error tags are enabled (`-gnatw.d') is to use a single +`-gnatw' tag string, enclosed in brackets, as shown in the example below, to treat one category of warnings as errors. Note that if you want to treat multiple categories of warnings as errors, you can use multiple pragma Warning_As_Error. @@ -9042,7 +9040,7 @@ you can use multiple pragma Warning_As_Error. The above use of patterns to match the message applies only to warning messages generated by the front end. This pragma can also be applied to warnings provided by the back end and mentioned in @ref{11a,,Pragma Warnings}. -By using a single full @emph{-Wxxx} switch in the pragma, such warnings +By using a single full `-Wxxx' switch in the pragma, such warnings can also be treated as errors. The pragma can appear either in a global configuration pragma file @@ -9055,7 +9053,7 @@ pragma Warning_As_Error ("[-gnatwj]"); which will treat all obsolescent feature warnings as errors, the following program compiles as shown (compile options here are -@emph{-gnatwa.d -gnatl -gnatj55}). +`-gnatwa.d -gnatl -gnatj55'). @example 1. pragma Warning_As_Error ("*never assigned*"); @@ -9116,7 +9114,7 @@ expression (which does not exist in Ada 83). Note if the second argument of @code{DETAILS} is a @code{local_NAME} then the second form is always understood. If the intention is to use the fourth form, then you can write @code{NAME & ""} to force the -intepretation as a @emph{static_string_EXPRESSION}. +intepretation as a `static_string_EXPRESSION'. Note: if the first argument is a valid @code{TOOL_NAME}, it will be interpreted that way. The use of the @code{TOOL_NAME} argument is relevant only to users @@ -9164,9 +9162,9 @@ The warnings controlled by the @code{-gnatw} switch are generated by the front end of the compiler. The GCC back end can provide additional warnings and they are controlled by the @code{-W} switch. Such warnings can be identified by the appearance of a string of the form @code{[-W@{xxx@}]} in the -message which designates the @code{-W@emph{xxx}} switch that controls the message. -The form with a single @emph{static_string_EXPRESSION} argument also works for these -warnings, but the string must be a single full @code{-W@emph{xxx}} switch in this +message which designates the @code{-W`xxx'} switch that controls the message. +The form with a single `static_string_EXPRESSION' argument also works for these +warnings, but the string must be a single full @code{-W`xxx'} switch in this case. The above reference lists a few examples of these additional warnings. The specified warnings will be in effect until the end of the program @@ -9179,7 +9177,7 @@ also be used as a configuration pragma. The fourth form, with an @code{On|Off} parameter and a string, is used to control individual messages, based on their text. The string argument is a pattern that is used to match against the text of individual -warning messages (not including the initial “warning: †tag). +warning messages (not including the initial “warning: “ tag). The pattern may contain asterisks, which match zero or more characters in the message. For example, you can use @@ -9196,7 +9194,7 @@ the end of the message, since this is implied). The above use of patterns to match the message applies only to warning messages generated by the front end. This form of the pragma with a string argument can also be used to control warnings provided by the back end and -mentioned above. By using a single full @code{-W@emph{xxx}} switch in the pragma, +mentioned above. By using a single full @code{-W`xxx'} switch in the pragma, such warnings can be turned on and off. There are two ways to use the pragma in this form. The OFF form can be used @@ -9214,7 +9212,7 @@ pragma Warnings (On, Pattern); @end example In this usage, the pattern string must match in the Off and On -pragmas, and (if @emph{-gnatw.w} is given) at least one matching +pragmas, and (if `-gnatw.w' is given) at least one matching warning must be suppressed. Note: if the ON form is not found, then the effect of the OFF form extends @@ -9471,15 +9469,15 @@ corresponding to @ref{29,,pragma Annotate}. @table @asis -@item @emph{Annotate => ID} +@item `Annotate => ID' Equivalent to @code{pragma Annotate (ID, Entity => Name);} -@item @emph{Annotate => (ID)} +@item `Annotate => (ID)' Equivalent to @code{pragma Annotate (ID, Entity => Name);} -@item @emph{Annotate => (ID ,ID @{, ARG@})} +@item `Annotate => (ID ,ID @{, ARG@})' Equivalent to @code{pragma Annotate (ID, ID @{, ARG@}, Entity => Name);} @end table @@ -10396,7 +10394,7 @@ supported by the target for the given type. @code{obj'Bit}, where @code{obj} is any object, yields the bit offset within the storage unit (byte) that contains the first bit of storage allocated for the object. The value of this attribute is of the -type @emph{universal_integer} and is always a nonnegative number smaller +type `universal_integer' and is always a nonnegative number smaller than @code{System.Storage_Unit}. For an object that is a variable or a constant allocated in a register, @@ -10428,7 +10426,7 @@ and implementation of the @code{Bit} attribute. of the fields of the record type, yields the bit offset within the record contains the first bit of storage allocated for the object. The value of this attribute is of the -type @emph{universal_integer}. The value depends only on the field +type `universal_integer'. The value depends only on the field @code{C} and is independent of the alignment of the containing record @code{R}. @@ -10775,7 +10773,7 @@ prefix) yields a static Boolean value that is True if pragma The prefix of attribute @code{Finalization_Size} must be an object or a non-class-wide type. This attribute returns the size of any hidden data reserved by the compiler to handle finalization-related actions. The type of -the attribute is @emph{universal_integer}. +the attribute is `universal_integer'. @code{Finalization_Size} yields a value of zero for a type with no controlled parts, an object whose type has no controlled parts, or an object of a @@ -11110,17 +11108,17 @@ the target. The result is a static constant. @code{func'Mechanism_Code} yields an integer code for the mechanism used for the result of function @code{func}, and @code{subprog'Mechanism_Code (n)} yields the mechanism -used for formal parameter number @emph{n} (a static integer value, with 1 +used for formal parameter number `n' (a static integer value, with 1 meaning the first parameter) of subprogram @code{subprog}. The code returned is: @table @asis -@item @emph{1} +@item `1' by copy (value) -@item @emph{2} +@item `2' by reference @end table @@ -11520,7 +11518,7 @@ the native ordering of the target, but this default can be overridden using pragma @code{Default_Scalar_Storage_Order}. If a component of @code{T} is itself of a record or array type, the specfied -@code{Scalar_Storage_Order} does @emph{not} apply to that nested type: an explicit +@code{Scalar_Storage_Order} does `not' apply to that nested type: an explicit attribute definition clause must be provided for the component type as well if desired. @@ -11624,7 +11622,7 @@ the primitive @code{Allocate} procedure for type @code{SSP}, passing @code{S'Simple_Storage_Pool} as the pool parameter. The detailed semantics of such allocators is the same as those defined for allocators in section 13.11 of the @cite{Ada Reference Manual}, with the term -@emph{simple storage pool} substituted for @emph{storage pool}. +`simple storage pool' substituted for `storage pool'. If an access type @code{S} has a specified simple storage pool of type @code{SSP}, then a call to an instance of the @code{Ada.Unchecked_Deallocation} @@ -11632,7 +11630,7 @@ for that access type invokes the primitive @code{Deallocate} procedure for type @code{SSP}, passing @code{S'Simple_Storage_Pool} as the pool parameter. The detailed semantics of such unchecked deallocations is the same as defined in section 13.11.2 of the Ada Reference Manual, except that the -term @emph{simple storage pool} is substituted for @emph{storage pool}. +term `simple storage pool' is substituted for `storage pool'. @node Attribute Small,Attribute Small_Denominator,Attribute Simple_Storage_Pool,Implementation Defined Attributes @anchor{gnat_rm/implementation_defined_attributes attribute-small}@anchor{19e} @@ -12576,7 +12574,9 @@ delay statements and no semantic dependences on package Calendar. @geindex No_Dependence [RM 13.12.1] This restriction ensures at compile time that there are no -dependences on a library unit. +dependences on a library unit. For GNAT, this includes implicit implementation +dependences on units of the runtime library that are created by the compiler +to support specific constructs of the language. @node No_Direct_Boolean_Operators,No_Dispatch,No_Dependence,Partition-Wide Restrictions @anchor{gnat_rm/standard_and_implementation_defined_restrictions no-direct-boolean-operators}@anchor{1cb} @@ -13923,7 +13923,7 @@ Explanation @item -@emph{Abort_Defer} +`Abort_Defer' @tab @@ -13931,7 +13931,7 @@ Affects semantics @item -@emph{Ada_83} +`Ada_83' @tab @@ -13939,7 +13939,7 @@ Affects legality @item -@emph{Assert} +`Assert' @tab @@ -13947,7 +13947,7 @@ Affects semantics @item -@emph{CPP_Class} +`CPP_Class' @tab @@ -13955,7 +13955,7 @@ Affects semantics @item -@emph{CPP_Constructor} +`CPP_Constructor' @tab @@ -13963,7 +13963,7 @@ Affects semantics @item -@emph{Debug} +`Debug' @tab @@ -13971,7 +13971,7 @@ Affects semantics @item -@emph{Interface_Name} +`Interface_Name' @tab @@ -13979,7 +13979,7 @@ Affects semantics @item -@emph{Machine_Attribute} +`Machine_Attribute' @tab @@ -13987,7 +13987,7 @@ Affects semantics @item -@emph{Unimplemented_Unit} +`Unimplemented_Unit' @tab @@ -13995,7 +13995,7 @@ Affects legality @item -@emph{Unchecked_Union} +`Unchecked_Union' @tab @@ -14160,7 +14160,7 @@ is a software rather than a hardware format. row-major order, consistent with the notation used for multidimensional array aggregates (see 4.3.3). However, if a pragma @code{Convention} (@code{Fortran}, …) applies to a multidimensional array type, then -column-major order should be used instead (see B.5, @emph{Interfacing with Fortran}).†+column-major order should be used instead (see B.5, `Interfacing with Fortran').†@end quotation Followed. @@ -14321,7 +14321,7 @@ The recommended level of support pragma @code{Pack} is: For a packed record type, the components should be packed as tightly as possible subject to the Sizes of the component subtypes, and subject to -any @emph{record_representation_clause} that applies to the type; the +any `record_representation_clause' that applies to the type; the implementation may, but need not, reorder components or cross aligned word boundaries to improve the packing. A component whose @code{Size} is greater than the word size may be allocated an integral number of words.†@@ -14579,7 +14579,7 @@ Followed. @quotation “The recommended level of support for -@emph{record_representation_clause}s is: +`record_representation_clause's is: An implementation should support storage places that can be extracted with a load, mask, shift sequence of machine code, and set with a load, @@ -14620,7 +14620,7 @@ clause for the tag field. @quotation -“An implementation need not support a @emph{component_clause} for a +“An implementation need not support a `component_clause' for a component of an extension part if the storage place is not after the storage places of all components of the parent type, whether or not those storage places had been specified.†@@ -15006,10 +15006,10 @@ packages. @quotation -“For each supported convention @emph{L} other than @code{Intrinsic}, an +“For each supported convention `L' other than @code{Intrinsic}, an implementation should support @code{Import} and @code{Export} pragmas -for objects of @emph{L}-compatible types and for subprograms, and pragma -@cite{Convention} for @emph{L}-eligible types and for subprograms, +for objects of `L'-compatible types and for subprograms, and pragma +@cite{Convention} for `L'-eligible types and for subprograms, presuming the other language has corresponding features. Pragma @code{Convention} need not be supported for scalar types.†@end quotation @@ -15482,10 +15482,10 @@ Followed. No such implementation-defined queuing policies exist. @quotation -“Even though the @emph{abort_statement} is included in the list of +“Even though the `abort_statement' is included in the list of potentially blocking operations (see 9.5.1), it is recommended that this statement be implemented in a way that never requires the task executing -the @emph{abort_statement} to block.†+the `abort_statement' to block.†@end quotation Followed. @@ -15841,7 +15841,7 @@ There are no variations from the standard. interactions. See 1.1.3(10).†@end itemize -Any @emph{code_statement} can potentially cause external interactions. +Any `code_statement' can potentially cause external interactions. @itemize * @@ -15882,8 +15882,8 @@ length. See 2.2(15).†The maximum line length is 255 characters and the maximum length of a lexical element is also 255 characters. This is the default setting -if not overridden by the use of compiler switch @emph{-gnaty} (which -sets the maximum to 79) or @emph{-gnatyMnn} which allows the maximum +if not overridden by the use of compiler switch `-gnaty' (which +sets the maximum to 79) or `-gnatyMnn' which allows the maximum line length to be specified to be any value up to 32767. The maximum length of a lexical element is the same as the maximum line length. @@ -15941,7 +15941,7 @@ Representation @item -@emph{Short_Short_Integer} +`Short_Short_Integer' @tab @@ -15949,7 +15949,7 @@ Representation @item -@emph{Short_Integer} +`Short_Integer' @tab @@ -15957,7 +15957,7 @@ Representation @item -@emph{Integer} +`Integer' @tab @@ -15965,7 +15965,7 @@ Representation @item -@emph{Long_Integer} +`Long_Integer' @tab @@ -15975,7 +15975,7 @@ depending on the C definition of long) @item -@emph{Long_Long_Integer} +`Long_Long_Integer' @tab @@ -15983,7 +15983,7 @@ depending on the C definition of long) @item -@emph{Long_Long_Long_Integer} +`Long_Long_Long_Integer' @tab @@ -16044,7 +16044,7 @@ Representation @item -@emph{Short_Float} +`Short_Float' @tab @@ -16052,7 +16052,7 @@ IEEE Binary32 (Single) @item -@emph{Float} +`Float' @tab @@ -16060,7 +16060,7 @@ IEEE Binary32 (Single) @item -@emph{Long_Float} +`Long_Float' @tab @@ -16068,7 +16068,7 @@ IEEE Binary64 (Double) @item -@emph{Long_Long_Float} +`Long_Long_Float' @tab @@ -16129,10 +16129,10 @@ small must lie in 1.0E-38 .. 1.0E+38 and the digits in 1 .. 38. @item “The result of @code{Tags.Expanded_Name} for types declared -within an unnamed @emph{block_statement}. See 3.9(10).†+within an unnamed `block_statement'. See 3.9(10).†@end itemize -Block numbers of the form @code{B@emph{nnn}}, where @emph{nnn} is a +Block numbers of the form @code{B@var{nnn}}, where `nnn' is a decimal integer are allocated. @@ -16233,7 +16233,7 @@ Difficult to characterize. “Any extensions of the Default_Initial_Condition aspect. See 7.3.3(11).†@end itemize -SPARK allows specifying @emph{null} as the Default_Initial_Condition +SPARK allows specifying `null' as the Default_Initial_Condition aspect of a type. See the SPARK reference manual for further details. @@ -16281,8 +16281,8 @@ setting for local time, as accessed by the C library function @itemize * @item -“Any limit on @emph{delay_until_statements} of -@emph{select_statements}. See 9.6(29).†+“Any limit on `delay_until_statements' of +`select_statements'. See 9.6(29).†@end itemize There are no such limits. @@ -16314,7 +16314,7 @@ There are no implementation-defined conflict check policies. @end itemize A compilation is represented by a sequence of files presented to the -compiler in a single invocation of the @emph{gcc} command. +compiler in a single invocation of the `gcc' command. @itemize * @@ -16358,11 +16358,11 @@ mentioned in the context clause of one of the needed Ada units. If the partition contains no main program, or if the main program is in a language other than Ada, then GNAT -provides the binder options @emph{-z} and @emph{-n} respectively, and in +provides the binder options `-z' and `-n' respectively, and in this case a list of units can be explicitly supplied to the binder for inclusion in the partition (all units needed by these units will also be included automatically). For full details on the use of these -options, refer to @emph{GNAT Make Program gnatmake} in the +options, refer to `GNAT Make Program gnatmake' in the @cite{GNAT User’s Guide}. @@ -16393,7 +16393,7 @@ corresponding @code{ALI} file as the input parameter to the binder. @itemize * @item -“The order of elaboration of @emph{library_items}. See 10.2(18).†+“The order of elaboration of `library_items'. See 10.2(18).†@end itemize The first constraint on ordering is that it meets the requirements of @@ -16465,11 +16465,11 @@ been passed by the program. @item “The result of @code{Exceptions.Exception_Name} for types -declared within an unnamed @emph{block_statement}. See 11.4.1(12).†+declared within an unnamed `block_statement'. See 11.4.1(12).†@end itemize -Blocks have implementation defined names of the form @code{B@emph{nnn}} -where @emph{nnn} is an integer. +Blocks have implementation defined names of the form @code{B@var{nnn}} +where `nnn' is an integer. @itemize * @@ -16735,7 +16735,7 @@ See the definition of package System.Storage_Elements in @code{s-stoele.ads}. @item “The contents of the visible part of package @code{System.Machine_Code}, -and the meaning of @emph{code_statements}. See 13.8(7).†+and the meaning of `code_statements'. See 13.8(7).†@end itemize See the definition and documentation in file @code{s-maccod.ads}. @@ -16969,7 +16969,7 @@ of the state vector. Annex is not supported. See A.5.3(72).†@end itemize -Running the compiler with @emph{-gnatS} to produce a listing of package +Running the compiler with `-gnatS' to produce a listing of package @code{Standard} displays the values of these attributes. @@ -17145,7 +17145,7 @@ Interpretation @item -@emph{Ada} +`Ada' @tab @@ -17153,7 +17153,7 @@ Ada @item -@emph{Ada_Pass_By_Copy} +`Ada_Pass_By_Copy' @tab @@ -17163,7 +17163,7 @@ with this convention to be passed by copy. @item -@emph{Ada_Pass_By_Reference} +`Ada_Pass_By_Reference' @tab @@ -17173,7 +17173,7 @@ with this convention to be passed by reference. @item -@emph{Assembler} +`Assembler' @tab @@ -17181,7 +17181,7 @@ Assembly language @item -@emph{Asm} +`Asm' @tab @@ -17189,7 +17189,7 @@ Synonym for Assembler @item -@emph{Assembly} +`Assembly' @tab @@ -17197,7 +17197,7 @@ Synonym for Assembler @item -@emph{C} +`C' @tab @@ -17205,7 +17205,7 @@ C @item -@emph{C_Pass_By_Copy} +`C_Pass_By_Copy' @tab @@ -17214,7 +17214,7 @@ is to be passed by copy rather than reference. @item -@emph{COBOL} +`COBOL' @tab @@ -17222,7 +17222,7 @@ COBOL @item -@emph{C_Plus_Plus (or CPP)} +`C_Plus_Plus (or CPP)' @tab @@ -17230,7 +17230,7 @@ C++ @item -@emph{Default} +`Default' @tab @@ -17238,7 +17238,7 @@ Treated the same as C @item -@emph{External} +`External' @tab @@ -17246,7 +17246,7 @@ Treated the same as C @item -@emph{Fortran} +`Fortran' @tab @@ -17254,7 +17254,7 @@ Fortran @item -@emph{Intrinsic} +`Intrinsic' @tab @@ -17263,7 +17263,7 @@ separate section on Intrinsic Subprograms. @item -@emph{Stdcall} +`Stdcall' @tab @@ -17274,7 +17274,7 @@ exit. This pragma cannot be applied to a dispatching call. @item -@emph{DLL} +`DLL' @tab @@ -17282,7 +17282,7 @@ Synonym for Stdcall @item -@emph{Win32} +`Win32' @tab @@ -17290,7 +17290,7 @@ Synonym for Stdcall @item -@emph{Stubbed} +`Stubbed' @tab @@ -17403,7 +17403,7 @@ Ada @item -@emph{Floating} +`Floating' @tab @@ -17411,7 +17411,7 @@ Float @item -@emph{Long_Floating} +`Long_Floating' @tab @@ -17419,7 +17419,7 @@ Float @item -@emph{Binary} +`Binary' @tab @@ -17427,7 +17427,7 @@ Integer @item -@emph{Long_Binary} +`Long_Binary' @tab @@ -17435,7 +17435,7 @@ Long_Long_Integer @item -@emph{Decimal_Element} +`Decimal_Element' @tab @@ -17443,7 +17443,7 @@ Character @item -@emph{COBOL_Character} +`COBOL_Character' @tab @@ -17540,12 +17540,12 @@ attribute. See C.7.1(7).†The result of this attribute is a string that identifies the object or component that denotes a given task. If a variable @code{Var} -has a task type, the image for this task will have the form @code{Var_@emph{XXXXXXXX}}, -where the suffix @emph{XXXXXXXX} +has a task type, the image for this task will have the form @code{Var_@var{XXXXXXXX}}, +where the suffix `XXXXXXXX' is the hexadecimal representation of the virtual address of the corresponding task control block. If the variable is an array of tasks, the image of each task will have the form of an indexed component indicating the position of a -given task in the array, e.g., @code{Group(5)_@emph{XXXXXXX}}. If the task is a +given task in the array, e.g., @code{Group(5)_@var{XXXXXXX}}. If the task is a component of a record, the image of the task will have the form of a selected component. These rules are fully recursive, so that the image of a task that is a subcomponent of a composite object corresponds to the expression that @@ -17648,7 +17648,7 @@ The value is 10 milliseconds. @itemize * @item -“Implementation-defined @emph{policy_identifiers} allowed +“Implementation-defined `policy_identifiers' allowed in a pragma @code{Locking_Policy}. See D.3(4).†@end itemize @@ -17900,7 +17900,7 @@ Value @item -@emph{Max_Scale} +`Max_Scale' @tab @@ -17908,7 +17908,7 @@ Value @item -@emph{Min_Scale} +`Min_Scale' @tab @@ -17916,7 +17916,7 @@ Value @item -@emph{Min_Delta} +`Min_Delta' @tab @@ -17924,7 +17924,7 @@ Value @item -@emph{Max_Delta} +`Max_Delta' @tab @@ -17932,7 +17932,7 @@ Value @item -@emph{Max_Decimal_Digits} +`Max_Decimal_Digits' @tab @@ -18024,7 +18024,7 @@ result type is @code{False}. See G.2.1(13).†Infinite and NaN values are produced as dictated by the IEEE floating-point standard. Note that on machines that are not fully compliant with the IEEE -floating-point standard, such as Alpha, the @emph{-mieee} compiler flag +floating-point standard, such as Alpha, the `-mieee' compiler flag must be used for achieving IEEE conforming behavior (although at the cost of a significant performance penalty), so infinite and NaN values are properly generated. @@ -18057,7 +18057,7 @@ is converted to the target type. @itemize * @item -“Conditions on a @emph{universal_real} operand of a fixed +“Conditions on a `universal_real' operand of a fixed point multiplication or division for which the result shall be in the perfect result set. See G.2.3(22).†@end itemize @@ -18476,7 +18476,7 @@ The default alignment values are as follows: @itemize * @item -@emph{Elementary Types}. +`Elementary Types'. For elementary types, the alignment is the minimum of the actual size of objects of the type divided by @code{Storage_Unit}, @@ -18493,7 +18493,7 @@ than 8, in which case objects of type @code{Long_Float} will be maximally aligned. @item -@emph{Arrays}. +`Arrays'. For arrays, the alignment is equal to the alignment of the component type for the normal case where no packing or component size is given. If the @@ -18506,7 +18506,7 @@ will be as described for elementary types, e.g. a packed array of length 31 bits will have an object size of four bytes, and an alignment of 4. @item -@emph{Records}. +`Records'. For the normal unpacked case, the alignment of a record is equal to the maximum alignment of any of its components. For tagged records, this @@ -18690,7 +18690,7 @@ Then @code{Default_Stack_Size} can be defined in a global package, and modified as required. Any tasks requiring stack sizes different from the default can have an appropriate alternative reference in the pragma. -You can also use the @emph{-d} binder switch to modify the default stack +You can also use the `-d' binder switch to modify the default stack size. For access types, the @code{Storage_Size} clause specifies the maximum @@ -18950,7 +18950,7 @@ discrete types are as follows: @item The @code{Object_Size} for base subtypes reflect the natural hardware -size in bits (run the compiler with @emph{-gnatS} to find those values +size in bits (run the compiler with `-gnatS' to find those values for numeric types). Enumeration types and fixed-point base subtypes have 8, 16, 32, or 64 bits for this size, depending on the range of values to be stored. @@ -19623,7 +19623,7 @@ an appropriate manner. @geindex Pragma Pack (for arrays) Pragma @code{Pack} applied to an array has an effect that depends upon whether the -component type is @emph{packable}. For a component type to be @emph{packable}, it must +component type is `packable'. For a component type to be `packable', it must be one of the following cases: @@ -19744,8 +19744,8 @@ since in this case the programmer intention is clear. Pragma @code{Pack} applied to a record will pack the components to reduce wasted space from alignment gaps and by reducing the amount of space -taken by components. We distinguish between @emph{packable} components and -@emph{non-packable} components. +taken by components. We distinguish between `packable' components and +`non-packable' components. Components of the following types are considered packable: @@ -19994,7 +19994,7 @@ be in the range: 0 .. System.Max_Binary_Modulus; @end example -A @emph{confirming} representation clause is one in which the values range +A `confirming' representation clause is one in which the values range from 0 in sequence, i.e., a clause that confirms the default representation for an enumeration type. Such a confirming representation @@ -20436,7 +20436,7 @@ There are four exceptions to this general rule: @itemize * @item -@emph{Convention Fortran and array subtypes}. +`Convention Fortran and array subtypes'. If pragma Convention Fortran is specified for an array subtype, then in accordance with the implementation advice in section 3.6.2(11) of the @@ -20444,7 +20444,7 @@ Ada Reference Manual, the array will be stored in a Fortran-compatible column-major manner, instead of the normal default row-major order. @item -@emph{Convention C and enumeration types} +`Convention C and enumeration types' GNAT normally stores enumeration types in 8, 16, or 32 bits as required to accommodate all values of the type. For example, for the enumeration @@ -20470,7 +20470,7 @@ warning in this situation. The warning can be suppressed by giving an explicit size clause specifying the desired size. @item -@emph{Convention C/Fortran and Boolean types} +`Convention C/Fortran and Boolean types' In C, the usual convention for boolean values, that is values used for conditions, is that zero represents false, and nonzero values represent @@ -20594,7 +20594,7 @@ fields placed? The section on pragma @code{Pack} in this chapter can be used to answer the second question, but it is often easier to just see what the compiler does. -For this purpose, GNAT provides the option @emph{-gnatR}. If you compile +For this purpose, GNAT provides the option `-gnatR'. If you compile with this option, then the compiler will output information on the actual representations chosen, in a format similar to source representation clauses. For example, if we compile the package: @@ -20643,7 +20643,7 @@ package q is end q; @end example -using the switch @emph{-gnatR} we obtain the following output: +using the switch `-gnatR' we obtain the following output: @example Representation information for unit q @@ -20753,56 +20753,56 @@ the unit is not implemented. @table @asis -@item @code{Ada} @emph{(A.2)} +@item @code{Ada} `(A.2)' This is a parent package for all the standard library packages. It is usually included implicitly in your program, and itself contains no useful data or routines. -@item @code{Ada.Assertions} @emph{(11.4.2)} +@item @code{Ada.Assertions} `(11.4.2)' @code{Assertions} provides the @code{Assert} subprograms, and also the declaration of the @code{Assertion_Error} exception. -@item @code{Ada.Asynchronous_Task_Control} @emph{(D.11)} +@item @code{Ada.Asynchronous_Task_Control} `(D.11)' @code{Asynchronous_Task_Control} provides low level facilities for task synchronization. It is typically not implemented. See package spec for details. -@item @code{Ada.Calendar} @emph{(9.6)} +@item @code{Ada.Calendar} `(9.6)' @code{Calendar} provides time of day access, and routines for manipulating times and durations. -@item @code{Ada.Calendar.Arithmetic} @emph{(9.6.1)} +@item @code{Ada.Calendar.Arithmetic} `(9.6.1)' This package provides additional arithmetic operations for @code{Calendar}. -@item @code{Ada.Calendar.Formatting} @emph{(9.6.1)} +@item @code{Ada.Calendar.Formatting} `(9.6.1)' This package provides formatting operations for @code{Calendar}. -@item @code{Ada.Calendar.Time_Zones} @emph{(9.6.1)} +@item @code{Ada.Calendar.Time_Zones} `(9.6.1)' This package provides additional @code{Calendar} facilities for handling time zones. -@item @code{Ada.Characters} @emph{(A.3.1)} +@item @code{Ada.Characters} `(A.3.1)' This is a dummy parent package that contains no useful entities -@item @code{Ada.Characters.Conversions} @emph{(A.3.2)} +@item @code{Ada.Characters.Conversions} `(A.3.2)' This package provides character conversion functions. -@item @code{Ada.Characters.Handling} @emph{(A.3.2)} +@item @code{Ada.Characters.Handling} `(A.3.2)' This package provides some basic character handling capabilities, including classification functions for classes of characters (e.g., test for letters, or digits). -@item @code{Ada.Characters.Latin_1} @emph{(A.3.3)} +@item @code{Ada.Characters.Latin_1} `(A.3.3)' This package includes a complete set of definitions of the characters that appear in type CHARACTER. It is useful for writing programs that @@ -20812,194 +20812,194 @@ the definition of @code{UC_E_Acute} in this package. Then your program will print in an understandable manner even if your environment does not support these extended characters. -@item @code{Ada.Command_Line} @emph{(A.15)} +@item @code{Ada.Command_Line} `(A.15)' This package provides access to the command line parameters and the name of the current program (analogous to the use of @code{argc} and @code{argv} in C), and also allows the exit status for the program to be set in a system-independent manner. -@item @code{Ada.Complex_Text_IO} @emph{(G.1.3)} +@item @code{Ada.Complex_Text_IO} `(G.1.3)' This package provides text input and output of complex numbers. -@item @code{Ada.Containers} @emph{(A.18.1)} +@item @code{Ada.Containers} `(A.18.1)' A top level package providing a few basic definitions used by all the following specific child packages that provide specific kinds of containers. @end table -@code{Ada.Containers.Bounded_Priority_Queues} @emph{(A.18.31)} +@code{Ada.Containers.Bounded_Priority_Queues} `(A.18.31)' -@code{Ada.Containers.Bounded_Synchronized_Queues} @emph{(A.18.29)} +@code{Ada.Containers.Bounded_Synchronized_Queues} `(A.18.29)' -@code{Ada.Containers.Doubly_Linked_Lists} @emph{(A.18.3)} +@code{Ada.Containers.Doubly_Linked_Lists} `(A.18.3)' -@code{Ada.Containers.Generic_Array_Sort} @emph{(A.18.26)} +@code{Ada.Containers.Generic_Array_Sort} `(A.18.26)' -@code{Ada.Containers.Generic_Constrained_Array_Sort} @emph{(A.18.26)} +@code{Ada.Containers.Generic_Constrained_Array_Sort} `(A.18.26)' -@code{Ada.Containers.Generic_Sort} @emph{(A.18.26)} +@code{Ada.Containers.Generic_Sort} `(A.18.26)' -@code{Ada.Containers.Hashed_Maps} @emph{(A.18.5)} +@code{Ada.Containers.Hashed_Maps} `(A.18.5)' -@code{Ada.Containers.Hashed_Sets} @emph{(A.18.8)} +@code{Ada.Containers.Hashed_Sets} `(A.18.8)' -@code{Ada.Containers.Indefinite_Doubly_Linked_Lists} @emph{(A.18.12)} +@code{Ada.Containers.Indefinite_Doubly_Linked_Lists} `(A.18.12)' -@code{Ada.Containers.Indefinite_Hashed_Maps} @emph{(A.18.13)} +@code{Ada.Containers.Indefinite_Hashed_Maps} `(A.18.13)' -@code{Ada.Containers.Indefinite_Hashed_Sets} @emph{(A.18.15)} +@code{Ada.Containers.Indefinite_Hashed_Sets} `(A.18.15)' -@code{Ada.Containers.Indefinite_Holders} @emph{(A.18.18)} +@code{Ada.Containers.Indefinite_Holders} `(A.18.18)' -@code{Ada.Containers.Indefinite_Multiway_Trees} @emph{(A.18.17)} +@code{Ada.Containers.Indefinite_Multiway_Trees} `(A.18.17)' -@code{Ada.Containers.Indefinite_Ordered_Maps} @emph{(A.18.14)} +@code{Ada.Containers.Indefinite_Ordered_Maps} `(A.18.14)' -@code{Ada.Containers.Indefinite_Ordered_Sets} @emph{(A.18.16)} +@code{Ada.Containers.Indefinite_Ordered_Sets} `(A.18.16)' -@code{Ada.Containers.Indefinite_Vectors} @emph{(A.18.11)} +@code{Ada.Containers.Indefinite_Vectors} `(A.18.11)' -@code{Ada.Containers.Multiway_Trees} @emph{(A.18.10)} +@code{Ada.Containers.Multiway_Trees} `(A.18.10)' -@code{Ada.Containers.Ordered_Maps} @emph{(A.18.6)} +@code{Ada.Containers.Ordered_Maps} `(A.18.6)' -@code{Ada.Containers.Ordered_Sets} @emph{(A.18.9)} +@code{Ada.Containers.Ordered_Sets} `(A.18.9)' -@code{Ada.Containers.Synchronized_Queue_Interfaces} @emph{(A.18.27)} +@code{Ada.Containers.Synchronized_Queue_Interfaces} `(A.18.27)' -@code{Ada.Containers.Unbounded_Priority_Queues} @emph{(A.18.30)} +@code{Ada.Containers.Unbounded_Priority_Queues} `(A.18.30)' -@code{Ada.Containers.Unbounded_Synchronized_Queues} @emph{(A.18.28)} +@code{Ada.Containers.Unbounded_Synchronized_Queues} `(A.18.28)' -@code{Ada.Containers.Vectors} @emph{(A.18.2)} +@code{Ada.Containers.Vectors} `(A.18.2)' @table @asis -@item @code{Ada.Directories} @emph{(A.16)} +@item @code{Ada.Directories} `(A.16)' This package provides operations on directories. -@item @code{Ada.Directories.Hierarchical_File_Names} @emph{(A.16.1)} +@item @code{Ada.Directories.Hierarchical_File_Names} `(A.16.1)' This package provides additional directory operations handling hiearchical file names. -@item @code{Ada.Directories.Information} @emph{(A.16)} +@item @code{Ada.Directories.Information} `(A.16)' This is an implementation defined package for additional directory operations, which is not implemented in GNAT. -@item @code{Ada.Decimal} @emph{(F.2)} +@item @code{Ada.Decimal} `(F.2)' This package provides constants describing the range of decimal numbers implemented, and also a decimal divide routine (analogous to the COBOL verb DIVIDE … GIVING … REMAINDER …) -@item @code{Ada.Direct_IO} @emph{(A.8.4)} +@item @code{Ada.Direct_IO} `(A.8.4)' This package provides input-output using a model of a set of records of fixed-length, containing an arbitrary definite Ada type, indexed by an integer record number. -@item @code{Ada.Dispatching} @emph{(D.2.1)} +@item @code{Ada.Dispatching} `(D.2.1)' A parent package containing definitions for task dispatching operations. -@item @code{Ada.Dispatching.EDF} @emph{(D.2.6)} +@item @code{Ada.Dispatching.EDF} `(D.2.6)' Not implemented in GNAT. -@item @code{Ada.Dispatching.Non_Preemptive} @emph{(D.2.4)} +@item @code{Ada.Dispatching.Non_Preemptive} `(D.2.4)' Not implemented in GNAT. -@item @code{Ada.Dispatching.Round_Robin} @emph{(D.2.5)} +@item @code{Ada.Dispatching.Round_Robin} `(D.2.5)' Not implemented in GNAT. -@item @code{Ada.Dynamic_Priorities} @emph{(D.5)} +@item @code{Ada.Dynamic_Priorities} `(D.5)' This package allows the priorities of a task to be adjusted dynamically as the task is running. -@item @code{Ada.Environment_Variables} @emph{(A.17)} +@item @code{Ada.Environment_Variables} `(A.17)' This package provides facilities for accessing environment variables. -@item @code{Ada.Exceptions} @emph{(11.4.1)} +@item @code{Ada.Exceptions} `(11.4.1)' This package provides additional information on exceptions, and also contains facilities for treating exceptions as data objects, and raising exceptions with associated messages. -@item @code{Ada.Execution_Time} @emph{(D.14)} +@item @code{Ada.Execution_Time} `(D.14)' This package provides CPU clock functionalities. It is not implemented on all targets (see package spec for details). -@item @code{Ada.Execution_Time.Group_Budgets} @emph{(D.14.2)} +@item @code{Ada.Execution_Time.Group_Budgets} `(D.14.2)' Not implemented in GNAT. -@item @code{Ada.Execution_Time.Timers} @emph{(D.14.1)’} +@item @code{Ada.Execution_Time.Timers} `(D.14.1)’' Not implemented in GNAT. -@item @code{Ada.Finalization} @emph{(7.6)} +@item @code{Ada.Finalization} `(7.6)' This package contains the declarations and subprograms to support the use of controlled types, providing for automatic initialization and finalization (analogous to the constructors and destructors of C++). -@item @code{Ada.Float_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Float_Text_IO} `(A.10.9)' A library level instantiation of Text_IO.Float_IO for type Float. -@item @code{Ada.Float_Wide_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Float_Wide_Text_IO} `(A.10.9)' A library level instantiation of Wide_Text_IO.Float_IO for type Float. -@item @code{Ada.Float_Wide_Wide_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Float_Wide_Wide_Text_IO} `(A.10.9)' A library level instantiation of Wide_Wide_Text_IO.Float_IO for type Float. -@item @code{Ada.Integer_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Integer_Text_IO} `(A.10.9)' A library level instantiation of Text_IO.Integer_IO for type Integer. -@item @code{Ada.Integer_Wide_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Integer_Wide_Text_IO} `(A.10.9)' A library level instantiation of Wide_Text_IO.Integer_IO for type Integer. -@item @code{Ada.Integer_Wide_Wide_Text_IO} @emph{(A.10.9)} +@item @code{Ada.Integer_Wide_Wide_Text_IO} `(A.10.9)' A library level instantiation of Wide_Wide_Text_IO.Integer_IO for type Integer. -@item @code{Ada.Interrupts} @emph{(C.3.2)} +@item @code{Ada.Interrupts} `(C.3.2)' This package provides facilities for interfacing to interrupts, which includes the set of signals or conditions that can be raised and recognized as interrupts. -@item @code{Ada.Interrupts.Names} @emph{(C.3.2)} +@item @code{Ada.Interrupts.Names} `(C.3.2)' This package provides the set of interrupt names (actually signal or condition names) that can be handled by GNAT. -@item @code{Ada.IO_Exceptions} @emph{(A.13)} +@item @code{Ada.IO_Exceptions} `(A.13)' This package defines the set of exceptions that can be raised by use of the standard IO packages. -@item @code{Ada.Iterator_Interfaces} @emph{(5.5.1)} +@item @code{Ada.Iterator_Interfaces} `(5.5.1)' This package provides a generic interface to generalized iterators. -@item @code{Ada.Locales} @emph{(A.19)} +@item @code{Ada.Locales} `(A.19)' This package provides declarations providing information (Language and Country) about the current locale. @@ -21011,7 +21011,7 @@ throughout the numerics packages. Note that the constants pi and e are defined here, and it is better to use these definitions than rolling your own. -@item @code{Ada.Numerics.Complex_Arrays} @emph{(G.3.2)} +@item @code{Ada.Numerics.Complex_Arrays} `(G.3.2)' Provides operations on arrays of complex numbers. @@ -21118,15 +21118,15 @@ The following predefined instantiations of this package exist @code{Ada.Numerics.Long_Elementary_Functions} @end itemize -@item @code{Ada.Numerics.Generic_Real_Arrays} @emph{(G.3.1)} +@item @code{Ada.Numerics.Generic_Real_Arrays} `(G.3.1)' Generic operations on arrays of reals -@item @code{Ada.Numerics.Real_Arrays} @emph{(G.3.1)} +@item @code{Ada.Numerics.Real_Arrays} `(G.3.1)' Preinstantiation of Ada.Numerics.Generic_Real_Arrays (Float). -@item @code{Ada.Real_Time} @emph{(D.8)} +@item @code{Ada.Real_Time} `(D.8)' This package provides facilities similar to those of @code{Calendar}, but operating with a finer clock suitable for real time control. Note that @@ -21135,29 +21135,29 @@ guarantees this behavior, but of course if the external clock on which the GNAT runtime depends is deliberately reset by some external event, then such a backward jump may occur. -@item @code{Ada.Real_Time.Timing_Events} @emph{(D.15)} +@item @code{Ada.Real_Time.Timing_Events} `(D.15)' Not implemented in GNAT. -@item @code{Ada.Sequential_IO} @emph{(A.8.1)} +@item @code{Ada.Sequential_IO} `(A.8.1)' This package provides input-output facilities for sequential files, which can contain a sequence of values of a single type, which can be any Ada type, including indefinite (unconstrained) types. -@item @code{Ada.Storage_IO} @emph{(A.9)} +@item @code{Ada.Storage_IO} `(A.9)' This package provides a facility for mapping arbitrary Ada types to and from a storage buffer. It is primarily intended for the creation of new IO packages. -@item @code{Ada.Streams} @emph{(13.13.1)} +@item @code{Ada.Streams} `(13.13.1)' This is a generic package that provides the basic support for the concept of streams as used by the stream attributes (@code{Input}, @code{Output}, @code{Read} and @code{Write}). -@item @code{Ada.Streams.Stream_IO} @emph{(A.12.1)} +@item @code{Ada.Streams.Stream_IO} `(A.12.1)' This package is a specialization of the type @code{Streams} defined in package @code{Streams} together with a set of operations providing @@ -21165,76 +21165,76 @@ Stream_IO capability. The Stream_IO model permits both random and sequential access to a file which can contain an arbitrary set of values of one or more Ada types. -@item @code{Ada.Strings} @emph{(A.4.1)} +@item @code{Ada.Strings} `(A.4.1)' This package provides some basic constants used by the string handling packages. -@item @code{Ada.Strings.Bounded} @emph{(A.4.4)} +@item @code{Ada.Strings.Bounded} `(A.4.4)' This package provides facilities for handling variable length strings. The bounded model requires a maximum length. It is thus somewhat more limited than the unbounded model, but avoids the use of dynamic allocation or finalization. -@item @code{Ada.Strings.Bounded.Equal_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Bounded.Equal_Case_Insensitive} `(A.4.10)' Provides case-insensitive comparisons of bounded strings -@item @code{Ada.Strings.Bounded.Hash} @emph{(A.4.9)} +@item @code{Ada.Strings.Bounded.Hash} `(A.4.9)' This package provides a generic hash function for bounded strings -@item @code{Ada.Strings.Bounded.Hash_Case_Insensitive} @emph{(A.4.9)} +@item @code{Ada.Strings.Bounded.Hash_Case_Insensitive} `(A.4.9)' This package provides a generic hash function for bounded strings that converts the string to be hashed to lower case. -@item @code{Ada.Strings.Bounded.Less_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Bounded.Less_Case_Insensitive} `(A.4.10)' This package provides a comparison function for bounded strings that works in a case insensitive manner by converting to lower case before the comparison. -@item @code{Ada.Strings.Fixed} @emph{(A.4.3)} +@item @code{Ada.Strings.Fixed} `(A.4.3)' This package provides facilities for handling fixed length strings. -@item @code{Ada.Strings.Fixed.Equal_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Fixed.Equal_Case_Insensitive} `(A.4.10)' This package provides an equality function for fixed strings that compares the strings after converting both to lower case. -@item @code{Ada.Strings.Fixed.Hash_Case_Insensitive} @emph{(A.4.9)} +@item @code{Ada.Strings.Fixed.Hash_Case_Insensitive} `(A.4.9)' This package provides a case insensitive hash function for fixed strings that converts the string to lower case before computing the hash. -@item @code{Ada.Strings.Fixed.Less_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Fixed.Less_Case_Insensitive} `(A.4.10)' This package provides a comparison function for fixed strings that works in a case insensitive manner by converting to lower case before the comparison. -@item @code{Ada.Strings.Hash} @emph{(A.4.9)} +@item @code{Ada.Strings.Hash} `(A.4.9)' This package provides a hash function for strings. -@item @code{Ada.Strings.Hash_Case_Insensitive} @emph{(A.4.9)} +@item @code{Ada.Strings.Hash_Case_Insensitive} `(A.4.9)' This package provides a hash function for strings that is case insensitive. The string is converted to lower case before computing the hash. -@item @code{Ada.Strings.Less_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Less_Case_Insensitive} `(A.4.10)' This package provides a comparison function for\strings that works in a case insensitive manner by converting to lower case before the comparison. -@item @code{Ada.Strings.Maps} @emph{(A.4.2)} +@item @code{Ada.Strings.Maps} `(A.4.2)' This package provides facilities for handling character mappings and arbitrarily defined subsets of characters. For instance it is useful in defining specialized translation tables. -@item @code{Ada.Strings.Maps.Constants} @emph{(A.4.6)} +@item @code{Ada.Strings.Maps.Constants} `(A.4.6)' This package provides a standard set of predefined mappings and predefined character sets. For example, the standard upper to lower case @@ -21244,62 +21244,62 @@ characters, including extended characters like E with an acute accent, into account. You should use the mappings in this package (rather than adding 32 yourself) to do case mappings. -@item @code{Ada.Strings.Unbounded} @emph{(A.4.5)} +@item @code{Ada.Strings.Unbounded} `(A.4.5)' This package provides facilities for handling variable length strings. The unbounded model allows arbitrary length strings, but requires the use of dynamic allocation and finalization. -@item @code{Ada.Strings.Unbounded.Equal_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Unbounded.Equal_Case_Insensitive} `(A.4.10)' Provides case-insensitive comparisons of unbounded strings -@item @code{Ada.Strings.Unbounded.Hash} @emph{(A.4.9)} +@item @code{Ada.Strings.Unbounded.Hash} `(A.4.9)' This package provides a generic hash function for unbounded strings -@item @code{Ada.Strings.Unbounded.Hash_Case_Insensitive} @emph{(A.4.9)} +@item @code{Ada.Strings.Unbounded.Hash_Case_Insensitive} `(A.4.9)' This package provides a generic hash function for unbounded strings that converts the string to be hashed to lower case. -@item @code{Ada.Strings.Unbounded.Less_Case_Insensitive} @emph{(A.4.10)} +@item @code{Ada.Strings.Unbounded.Less_Case_Insensitive} `(A.4.10)' This package provides a comparison function for unbounded strings that works in a case insensitive manner by converting to lower case before the comparison. -@item @code{Ada.Strings.UTF_Encoding} @emph{(A.4.11)} +@item @code{Ada.Strings.UTF_Encoding} `(A.4.11)' This package provides basic definitions for dealing with UTF-encoded strings. -@item @code{Ada.Strings.UTF_Encoding.Conversions} @emph{(A.4.11)} +@item @code{Ada.Strings.UTF_Encoding.Conversions} `(A.4.11)' This package provides conversion functions for UTF-encoded strings. @end table -@code{Ada.Strings.UTF_Encoding.Strings} @emph{(A.4.11)} +@code{Ada.Strings.UTF_Encoding.Strings} `(A.4.11)' -@code{Ada.Strings.UTF_Encoding.Wide_Strings} @emph{(A.4.11)} +@code{Ada.Strings.UTF_Encoding.Wide_Strings} `(A.4.11)' @table @asis -@item @code{Ada.Strings.UTF_Encoding.Wide_Wide_Strings} @emph{(A.4.11)} +@item @code{Ada.Strings.UTF_Encoding.Wide_Wide_Strings} `(A.4.11)' These packages provide facilities for handling UTF encodings for Strings, Wide_Strings and Wide_Wide_Strings. @end table -@code{Ada.Strings.Wide_Bounded} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Bounded} `(A.4.7)' -@code{Ada.Strings.Wide_Fixed} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Fixed} `(A.4.7)' -@code{Ada.Strings.Wide_Maps} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Maps} `(A.4.7)' @table @asis -@item @code{Ada.Strings.Wide_Unbounded} @emph{(A.4.7)} +@item @code{Ada.Strings.Wide_Unbounded} `(A.4.7)' These packages provide analogous capabilities to the corresponding packages without @code{Wide_} in the name, but operate with the types @@ -21307,33 +21307,33 @@ packages without @code{Wide_} in the name, but operate with the types and @code{Character}. Versions of all the child packages are available. @end table -@code{Ada.Strings.Wide_Wide_Bounded} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Wide_Bounded} `(A.4.7)' -@code{Ada.Strings.Wide_Wide_Fixed} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Wide_Fixed} `(A.4.7)' -@code{Ada.Strings.Wide_Wide_Maps} @emph{(A.4.7)} +@code{Ada.Strings.Wide_Wide_Maps} `(A.4.7)' @table @asis -@item @code{Ada.Strings.Wide_Wide_Unbounded} @emph{(A.4.7)} +@item @code{Ada.Strings.Wide_Wide_Unbounded} `(A.4.7)' These packages provide analogous capabilities to the corresponding packages without @code{Wide_} in the name, but operate with the types @code{Wide_Wide_String} and @code{Wide_Wide_Character} instead of @code{String} and @code{Character}. -@item @code{Ada.Synchronous_Barriers} @emph{(D.10.1)} +@item @code{Ada.Synchronous_Barriers} `(D.10.1)' This package provides facilities for synchronizing tasks at a low level with barriers. -@item @code{Ada.Synchronous_Task_Control} @emph{(D.10)} +@item @code{Ada.Synchronous_Task_Control} `(D.10)' This package provides some standard facilities for controlling task communication in a synchronous manner. -@item @code{Ada.Synchronous_Task_Control.EDF} @emph{(D.10)} +@item @code{Ada.Synchronous_Task_Control.EDF} `(D.10)' Not implemented in GNAT. @@ -21342,21 +21342,21 @@ Not implemented in GNAT. This package contains definitions for manipulation of the tags of tagged values. -@item @code{Ada.Tags.Generic_Dispatching_Constructor} @emph{(3.9)} +@item @code{Ada.Tags.Generic_Dispatching_Constructor} `(3.9)' This package provides a way of constructing tagged class-wide values given only the tag value. -@item @code{Ada.Task_Attributes} @emph{(C.7.2)} +@item @code{Ada.Task_Attributes} `(C.7.2)' This package provides the capability of associating arbitrary task-specific data with separate tasks. -@item @code{Ada.Task_Identifification} @emph{(C.7.1)} +@item @code{Ada.Task_Identifification} `(C.7.1)' This package provides capabilities for task identification. -@item @code{Ada.Task_Termination} @emph{(C.7.3)} +@item @code{Ada.Task_Termination} `(C.7.3)' This package provides control over task termination. @@ -21520,12 +21520,12 @@ unchecked conversion nor Ada.Address_To_Access_Conversions should be used in conjunction with pointers to unconstrained objects, since the bounds information cannot be handled correctly in this case. -@item @code{Ada.Unchecked_Deallocation} @emph{(13.11.2)} +@item @code{Ada.Unchecked_Deallocation} `(13.11.2)' This generic package allows explicit freeing of storage previously allocated by use of an allocator. -@item @code{Ada.Wide_Text_IO} @emph{(A.11)} +@item @code{Ada.Wide_Text_IO} `(A.11)' This package is similar to @code{Ada.Text_IO}, except that the external file supports wide character representations, and the internal types are @@ -21533,7 +21533,7 @@ file supports wide character representations, and the internal types are and @code{String}. The corresponding set of nested packages and child packages are defined. -@item @code{Ada.Wide_Wide_Text_IO} @emph{(A.11)} +@item @code{Ada.Wide_Wide_Text_IO} `(A.11)' This package is similar to @code{Ada.Text_IO}, except that the external file supports wide character representations, and the internal types are @@ -22070,7 +22070,7 @@ Encoding @item -@emph{h} +`h' @tab @@ -22078,7 +22078,7 @@ Hex ESC encoding @item -@emph{u} +`u' @tab @@ -22086,7 +22086,7 @@ Upper half encoding @item -@emph{s} +`s' @tab @@ -22094,7 +22094,7 @@ Shift-JIS encoding @item -@emph{e} +`e' @tab @@ -22102,7 +22102,7 @@ EUC Encoding @item -@emph{8} +`8' @tab @@ -22110,7 +22110,7 @@ UTF-8 encoding @item -@emph{b} +`b' @tab @@ -22133,7 +22133,7 @@ being brackets encoding if no coding method was specified with -gnatW). @table @asis -@item @emph{Hex Coding} +@item `Hex Coding' In this encoding, a wide character is represented by a five character sequence: @@ -22156,7 +22156,7 @@ example, ESC A345 is used to represent the wide character with code @table @asis -@item @emph{Upper Half Coding} +@item `Upper Half Coding' The wide character with encoding 16#abcd#, where the upper bit is on (i.e., a is in the range 8-F) is represented as two bytes 16#ab# and @@ -22164,7 +22164,7 @@ The wide character with encoding 16#abcd#, where the upper bit is on not required to be in the upper half. This method can be also used for shift-JIS or EUC where the internal coding matches the external coding. -@item @emph{Shift JIS Coding} +@item `Shift JIS Coding' A wide character is represented by a two character sequence 16#ab# and 16#cd#, with the restrictions described for upper half encoding as @@ -22173,7 +22173,7 @@ character according to the standard algorithm for Shift-JIS conversion. Only characters defined in the JIS code set table can be used with this encoding method. -@item @emph{EUC Coding} +@item `EUC Coding' A wide character is represented by a two character sequence 16#ab# and 16#cd#, with both characters being in the upper half. The internal @@ -22181,7 +22181,7 @@ character code is the corresponding JIS character according to the EUC encoding algorithm. Only characters defined in the JIS code set table can be used with this encoding method. -@item @emph{UTF-8 Coding} +@item `UTF-8 Coding' A wide character is represented using UCS Transformation Format 8 (UTF-8) as defined in Annex R of ISO @@ -22211,7 +22211,7 @@ will all invalid UTF-8 sequences.) @table @asis -@item @emph{Brackets Coding} +@item `Brackets Coding' In this encoding, a wide character is represented by the following eight character sequence: @@ -22352,7 +22352,7 @@ Encoding @item -@emph{h} +`h' @tab @@ -22360,7 +22360,7 @@ Hex ESC encoding @item -@emph{u} +`u' @tab @@ -22368,7 +22368,7 @@ Upper half encoding @item -@emph{s} +`s' @tab @@ -22376,7 +22376,7 @@ Shift-JIS encoding @item -@emph{e} +`e' @tab @@ -22384,7 +22384,7 @@ EUC Encoding @item -@emph{8} +`8' @tab @@ -22392,7 +22392,7 @@ UTF-8 encoding @item -@emph{b} +`b' @tab @@ -22415,7 +22415,7 @@ being brackets encoding if no coding method was specified with -gnatW). @table @asis -@item @emph{UTF-8 Coding} +@item `UTF-8 Coding' A wide character is represented using UCS Transformation Format 8 (UTF-8) as defined in Annex R of ISO @@ -22443,7 +22443,7 @@ characters. @table @asis -@item @emph{Brackets Coding} +@item `Brackets Coding' In this encoding, a wide wide character is represented by the following eight character sequence if is in wide character range @@ -22673,11 +22673,11 @@ variable. And if not set @code{utf8} is assumed. @table @asis -@item @emph{CP_ACP} +@item `CP_ACP' The current system Windows ANSI code page. -@item @emph{CP_UTF8} +@item `CP_UTF8' UTF-8 encoding @end table @@ -22700,19 +22700,19 @@ The possible values are those supported on Windows: @table @asis -@item @emph{TEXT} +@item `TEXT' Translated text mode -@item @emph{WTEXT} +@item `WTEXT' Translated unicode encoding -@item @emph{U16TEXT} +@item `U16TEXT' Unicode 16-bit encoding -@item @emph{U8TEXT} +@item `U8TEXT' Unicode 8-bit encoding @end table @@ -22741,11 +22741,11 @@ using the mode shown in the following table: @tab -@strong{OPEN} +`OPEN' @tab -@strong{CREATE} +`CREATE' @item @@ -24176,7 +24176,7 @@ C @code{timeval} format. This package implements the CRC-32 algorithm. For a full description of this algorithm see -@emph{Computation of Cyclic Redundancy Checks via Table Look-Up}, +`Computation of Cyclic Redundancy Checks via Table Look-Up', @cite{Communications of the ACM}, Vol. 31 No. 8, pp. 1008-1013, Aug. 1988. Sarwate, D.V. @@ -25846,7 +25846,7 @@ See @ref{7,,Implementation Defined Pragmas}, for more details. @table @asis -@item @code{pragma CPP_Class ([Entity =>] @emph{LOCAL_NAME})} +@item @code{pragma CPP_Class ([Entity =>] @var{LOCAL_NAME})} The argument denotes an entity in the current declarative region that is declared as a tagged or untagged record type. It indicates that the type @@ -25857,7 +25857,7 @@ Note: Pragma @code{CPP_Class} is currently obsolete. It is supported for backward compatibility but its functionality is available using pragma @code{Import} with @code{Convention} = @code{CPP}. -@item @code{pragma CPP_Constructor ([Entity =>] @emph{LOCAL_NAME})} +@item @code{pragma CPP_Constructor ([Entity =>] @var{LOCAL_NAME})} This pragma identifies an imported function (imported in the usual way with pragma @code{Import}) as corresponding to a C++ constructor. @@ -25941,30 +25941,30 @@ GNAT implements all of these annexes: @table @asis -@item @emph{Systems Programming (Annex C)} +@item `Systems Programming (Annex C)' The Systems Programming Annex is fully implemented. -@item @emph{Real-Time Systems (Annex D)} +@item `Real-Time Systems (Annex D)' The Real-Time Systems Annex is fully implemented. -@item @emph{Distributed Systems (Annex E)} +@item `Distributed Systems (Annex E)' Stub generation is fully implemented in the GNAT compiler. In addition, a complete compatible PCS is available as part of the GLADE system, a separate product. When the two products are used in conjunction, this annex is fully implemented. -@item @emph{Information Systems (Annex F)} +@item `Information Systems (Annex F)' The Information Systems annex is fully implemented. -@item @emph{Numerics (Annex G)} +@item `Numerics (Annex G)' The Numerics Annex is fully implemented. -@item @emph{Safety and Security / High-Integrity Systems (Annex H)} +@item `Safety and Security / High-Integrity Systems (Annex H)' The Safety and Security Annex (termed the High-Integrity Systems Annex in Ada 2005) is fully implemented. @@ -26079,7 +26079,7 @@ No support is provided for GNU C’s symbolic names for input parameters. If there are no input operands, this argument may either be omitted, or explicitly given as @code{No_Input_Operands}. The fourth argument, not present in the above example, is a list of register names, called the -@emph{clobber} argument. This argument, if given, must be a static string +`clobber' argument. This argument, if given, must be a static string expression, and is a space or comma separated list of names of registers that must be considered destroyed as a result of the @code{Asm} call. If this argument is the null string (the default value), then the code @@ -26088,7 +26088,7 @@ In addition to registers, the special clobbers @code{memory} and @code{cc} as described in the GNU C docs are both supported. The fifth argument, not present in the above example, called the -@emph{volatile} argument, is by default @code{False}. It can be set to +`volatile' argument, is by default @code{False}. It can be set to the literal value @code{True} to indicate to the code generator that all optimizations with respect to the instruction specified should be suppressed, and in particular an instruction that has outputs @@ -26259,13 +26259,13 @@ scheduling policy states: @quotation -@emph{When the active priority of a ready task that is not running +`When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority, except in the case where the active priority is lowered due to the loss of inherited priority, in which case the task is -added at the head of the ready queue for its new active priority.} +added at the head of the ready queue for its new active priority.' @end quotation While most kernels do put tasks at the end of the priority queue when @@ -26354,7 +26354,7 @@ extensive usage as follows: @table @asis -@item @emph{Communication between separate programs} +@item `Communication between separate programs' This allows separate programs to access the data in passive partitions, using protected objects for synchronization where @@ -26364,7 +26364,7 @@ running on different machines with different architectures (e.g., different endianness) to communicate via the data in a passive partition. -@item @emph{Persistence between program runs} +@item `Persistence between program runs' The data in a passive package can persist from one run of a program to another, so that a later program sees the final @@ -26618,7 +26618,7 @@ end T; Word : Rec; @end example -Such an object is said to be @emph{unconstrained}. +Such an object is said to be `unconstrained'. The discriminant of the object can be modified by a full assignment to the object, as long as it preserves the relation between the value of the discriminant, and the value of the components @@ -26671,7 +26671,7 @@ index type of ‘reasonable’ range so that unconstrained objects are not too large. One final wrinkle: if the object is declared to be @code{aliased}, or if it is -created in the heap by means of an allocator, then it is @emph{not} +created in the heap by means of an allocator, then it is `not' unconstrained: it is constrained by the default values of the discriminants, and those values cannot be modified by full assignment. This is because in the presence of @@ -26714,15 +26714,15 @@ perform this check by default). Strict conformance to the Ada Reference Manual can be achieved by adding two compiler options for dynamic checks for access-before-elaboration on subprogram -calls and generic instantiations (@emph{-gnatE}), and stack overflow checking -(@emph{-fstack-check}). +calls and generic instantiations (`-gnatE'), and stack overflow checking +(`-fstack-check'). Note that the result of a floating point arithmetic operation in overflow and invalid situations, when the @code{Machine_Overflows} attribute of the result type is @code{False}, is to generate IEEE NaN and infinite values. This is the case for machines compliant with the IEEE floating-point standard, but on machines that are not fully compliant with this standard, such as Alpha, the -@emph{-mieee} compiler flag must be used for achieving IEEE confirming +`-mieee' compiler flag must be used for achieving IEEE confirming behavior (although at the cost of a significant performance penalty), so infinite and NaN values are properly generated. @@ -26744,7 +26744,7 @@ infinite and NaN values are properly generated. This chapter contains a complete list of Ada 2012 features that have been implemented. Generally, these features are only -available if the @emph{-gnat12} (Ada 2012 features enabled) option is set, +available if the `-gnat12' (Ada 2012 features enabled) option is set, which is the default behavior, or if the configuration pragma @code{Ada_2012} is used. @@ -26776,7 +26776,7 @@ A complete description of the AIs may be found in @itemize * @item -@emph{AI-0176 Quantified expressions (2010-09-29)} +`AI-0176 Quantified expressions (2010-09-29)' Both universally and existentially quantified expressions are implemented. They use the new syntax for iterators proposed in AI05-139-2, as well as @@ -26791,9 +26791,9 @@ RM References: 1.01.04 (12) 2.09 (2/2) 4.04 (7) 4.05.09 (0) @itemize * @item -@emph{AI-0079 Allow other_format characters in source (2010-07-10)} +`AI-0079 Allow other_format characters in source (2010-07-10)' -Wide characters in the unicode category @emph{other_format} are now allowed in +Wide characters in the unicode category `other_format' are now allowed in source programs between tokens, but not within a token such as an identifier. RM References: 2.01 (4/2) 2.02 (7) @@ -26805,9 +26805,9 @@ RM References: 2.01 (4/2) 2.02 (7) @itemize * @item -@emph{AI-0091 Do not allow other_format in identifiers (0000-00-00)} +`AI-0091 Do not allow other_format in identifiers (0000-00-00)' -Wide characters in the unicode category @emph{other_format} are not permitted +Wide characters in the unicode category `other_format' are not permitted within an identifier, since this can be a security problem. The error message for this case has been improved to be more specific, but GNAT has never allowed such characters to appear in identifiers. @@ -26821,7 +26821,7 @@ RM References: 2.03 (3.1/2) 2.03 (4/2) 2.03 (5/2) 2.03 (5.1/2) 2.03 (5. @itemize * @item -@emph{AI-0100 Placement of pragmas (2010-07-01)} +`AI-0100 Placement of pragmas (2010-07-01)' This AI is an earlier version of AI-163. It simplifies the rules for legal placement of pragmas. In the case of lists that allow pragmas, if @@ -26836,7 +26836,7 @@ RM References: 2.08 (7) @itemize * @item -@emph{AI-0163 Pragmas in place of null (2010-07-01)} +`AI-0163 Pragmas in place of null (2010-07-01)' A statement sequence may be composed entirely of pragmas. It is no longer necessary to add a dummy @code{null} statement to make the sequence legal. @@ -26850,7 +26850,7 @@ RM References: 2.08 (7) 2.08 (16) @itemize * @item -@emph{AI-0080 ‘View of’ not needed if clear from context (0000-00-00)} +`AI-0080 ‘View of’ not needed if clear from context (0000-00-00)' This is an editorial change only, described as non-testable in the AI. @@ -26863,7 +26863,7 @@ RM References: 3.01 (7) @itemize * @item -@emph{AI-0183 Aspect specifications (2010-08-16)} +`AI-0183 Aspect specifications (2010-08-16)' Aspect specifications have been fully implemented except for pre and post- conditions, and type invariants, which have their own separate AI’s. All @@ -27221,7 +27221,7 @@ RM References: 3.02.01 (3) 3.02.02 (2) 3.03.01 (2/2) 3.08 (6) @itemize * @item -@emph{AI-0128 Inequality is a primitive operation (0000-00-00)} +`AI-0128 Inequality is a primitive operation (0000-00-00)' If an equality operator (“=â€) is declared for a type, then the implicitly declared inequality operator (“/=â€) is a primitive operation of the type. @@ -27237,7 +27237,7 @@ RM References: 3.02.03 (6) 6.06 (6) @itemize * @item -@emph{AI-0003 Qualified expressions as names (2010-07-11)} +`AI-0003 Qualified expressions as names (2010-07-11)' In Ada 2012, a qualified expression is considered to be syntactically a name, meaning that constructs such as @code{A'(F(X)).B} are now legal. This is @@ -27253,7 +27253,7 @@ RM References: 3.03 (11) 3.03 (21) 4.01 (2) 4.04 (7) 4.07 (3) @itemize * @item -@emph{AI-0120 Constant instance of protected object (0000-00-00)} +`AI-0120 Constant instance of protected object (0000-00-00)' This is an RM editorial change only. The section that lists objects that are constant failed to include the current instance of a protected object @@ -27269,7 +27269,7 @@ RM References: 3.03 (21) @itemize * @item -@emph{AI-0008 General access to constrained objects (0000-00-00)} +`AI-0008 General access to constrained objects (0000-00-00)' The wording in the RM implied that if you have a general access to a constrained object, it could be used to modify the discriminants. This was @@ -27285,7 +27285,7 @@ RM References: 3.03 (23) 3.10.02 (26/2) 4.01 (9) 6.04.01 (17) 8.05.01 ( @itemize * @item -@emph{AI-0093 Additional rules use immutably limited (0000-00-00)} +`AI-0093 Additional rules use immutably limited (0000-00-00)' This is an editorial change only, to make more widespread use of the Ada 2012 ‘immutably limited’. @@ -27299,7 +27299,7 @@ RM References: 3.03 (23.4/3) @itemize * @item -@emph{AI-0096 Deriving from formal private types (2010-07-20)} +`AI-0096 Deriving from formal private types (2010-07-20)' In general it is illegal for a type derived from a formal limited type to be nonlimited. This AI makes an exception to this rule: derivation is legal @@ -27316,7 +27316,7 @@ RM References: 3.04 (5.1/2) 6.02 (7) @itemize * @item -@emph{AI-0181 Soft hyphen is a non-graphic character (2010-07-23)} +`AI-0181 Soft hyphen is a non-graphic character (2010-07-23)' From Ada 2005 on, soft hyphen is considered a non-graphic character, which means that it has a special name (@code{SOFT_HYPHEN}) in conjunction with the @@ -27333,7 +27333,7 @@ RM References: 3.05.02 (2/2) A.01 (35/2) A.03.03 (21) @itemize * @item -@emph{AI-0182 Additional forms for} @code{Character'Value} @emph{(0000-00-00)} +`AI-0182 Additional forms for' @code{Character'Value} `(0000-00-00)' This AI allows @code{Character'Value} to accept the string @code{'?'} where @code{?} is any character including non-graphic control characters. GNAT has @@ -27351,7 +27351,7 @@ RM References: 3.05 (56/2) @itemize * @item -@emph{AI-0214 Defaulted discriminants for limited tagged (2010-10-01)} +`AI-0214 Defaulted discriminants for limited tagged (2010-10-01)' Ada 2012 relaxes the restriction that forbids discriminants of tagged types to have default expressions by allowing them when the type is limited. It @@ -27367,7 +27367,7 @@ RM References: 3.07 (9.1/2) 3.07.02 (3) @itemize * @item -@emph{AI-0102 Some implicit conversions are illegal (0000-00-00)} +`AI-0102 Some implicit conversions are illegal (0000-00-00)' It is illegal to assign an anonymous access constant to an anonymous access variable. The RM did not have a clear rule to prevent this, but GNAT has @@ -27382,7 +27382,7 @@ RM References: 3.07 (16) 3.07.01 (9) 6.04.01 (6) 8.06 (27/2) @itemize * @item -@emph{AI-0158 Generalizing membership tests (2010-09-16)} +`AI-0158 Generalizing membership tests (2010-09-16)' This AI extends the syntax of membership tests to simplify complex conditions that can be expressed as membership in a subset of values of any type. It @@ -27398,7 +27398,7 @@ RM References: 3.08.01 (5) 4.04 (3) 4.05.02 (3) 4.05.02 (5) 4.05.02 (27 @itemize * @item -@emph{AI-0173 Testing if tags represent abstract types (2010-07-03)} +`AI-0173 Testing if tags represent abstract types (2010-07-03)' The function @code{Ada.Tags.Type_Is_Abstract} returns @code{True} if invoked with the tag of an abstract type, and @code{False} otherwise. @@ -27412,7 +27412,7 @@ RM References: 3.09 (7.4/2) 3.09 (12.4/2) @itemize * @item -@emph{AI-0076 function with controlling result (0000-00-00)} +`AI-0076 function with controlling result (0000-00-00)' This is an editorial change only. The RM defines calls with controlling results, but uses the term ‘function with controlling result’ without an @@ -27427,7 +27427,7 @@ RM References: 3.09.02 (2/2) @itemize * @item -@emph{AI-0126 Dispatching with no declared operation (0000-00-00)} +`AI-0126 Dispatching with no declared operation (0000-00-00)' This AI clarifies dispatching rules, and simply confirms that dispatching executes the operation of the parent type when there is no explicitly or @@ -27443,7 +27443,7 @@ RM References: 3.09.02 (20/2) 3.09.02 (20.1/2) 3.09.02 (20.2/2) @itemize * @item -@emph{AI-0097 Treatment of abstract null extension (2010-07-19)} +`AI-0097 Treatment of abstract null extension (2010-07-19)' The RM as written implied that in some cases it was possible to create an object of an abstract type, by having an abstract extension inherit a non- @@ -27459,7 +27459,7 @@ RM References: 3.09.03 (4/2) @itemize * @item -@emph{AI-0203 Extended return cannot be abstract (0000-00-00)} +`AI-0203 Extended return cannot be abstract (0000-00-00)' A return_subtype_indication cannot denote an abstract subtype. GNAT has never permitted such usage. @@ -27473,7 +27473,7 @@ RM References: 3.09.03 (8/3) @itemize * @item -@emph{AI-0198 Inheriting abstract operators (0000-00-00)} +`AI-0198 Inheriting abstract operators (0000-00-00)' This AI resolves a conflict between two rules involving inherited abstract operations and predefined operators. If a derived numeric type inherits @@ -27489,7 +27489,7 @@ RM References: 3.09.03 (4/3) @itemize * @item -@emph{AI-0073 Functions returning abstract types (2010-07-10)} +`AI-0073 Functions returning abstract types (2010-07-10)' This AI covers a number of issues regarding returning abstract types. In particular generic functions cannot have abstract result types or access @@ -27507,7 +27507,7 @@ RM References: 3.09.03 (8) 3.09.03 (10) 6.05 (8/2) @itemize * @item -@emph{AI-0070 Elaboration of interface types (0000-00-00)} +`AI-0070 Elaboration of interface types (0000-00-00)' This is an editorial change only, there are no testable consequences short of checking for the absence of generated code for an interface declaration. @@ -27521,7 +27521,7 @@ RM References: 3.09.04 (18/2) @itemize * @item -@emph{AI-0208 Characteristics of incomplete views (0000-00-00)} +`AI-0208 Characteristics of incomplete views (0000-00-00)' The wording in the Ada 2005 RM concerning characteristics of incomplete views was incorrect and implied that some programs intended to be legal were now @@ -27537,7 +27537,7 @@ RM References: 3.10.01 (2.4/2) 3.10.01 (2.6/2) @itemize * @item -@emph{AI-0162 Incomplete type completed by partial view (2010-09-15)} +`AI-0162 Incomplete type completed by partial view (2010-09-15)' Incomplete types are made more useful by allowing them to be completed by private types and private extensions. @@ -27551,7 +27551,7 @@ RM References: 3.10.01 (2.5/2) 3.10.01 (2.6/2) 3.10.01 (3) 3.10.01 (4/2) @itemize * @item -@emph{AI-0098 Anonymous subprogram access restrictions (0000-00-00)} +`AI-0098 Anonymous subprogram access restrictions (0000-00-00)' An unintentional omission in the RM implied some inconsistent restrictions on the use of anonymous access to subprogram values. These restrictions were not @@ -27566,7 +27566,7 @@ RM References: 3.10.01 (6) 3.10.01 (9.2/2) @itemize * @item -@emph{AI-0199 Aggregate with anonymous access components (2010-07-14)} +`AI-0199 Aggregate with anonymous access components (2010-07-14)' A choice list in a record aggregate can include several components of (distinct) anonymous access types as long as they have matching designated @@ -27581,7 +27581,7 @@ RM References: 4.03.01 (16) @itemize * @item -@emph{AI-0220 Needed components for aggregates (0000-00-00)} +`AI-0220 Needed components for aggregates (0000-00-00)' This AI addresses a wording problem in the RM that appears to permit some complex cases of aggregates with nonstatic discriminants. GNAT has always @@ -27596,7 +27596,7 @@ RM References: 4.03.01 (17) @itemize * @item -@emph{AI-0147 Conditional expressions (2009-03-29)} +`AI-0147 Conditional expressions (2009-03-29)' Conditional expressions are permitted. The form of such an expression is: @@ -27605,10 +27605,10 @@ Conditional expressions are permitted. The form of such an expression is: @end example The parentheses can be omitted in contexts where parentheses are present -anyway, such as subprogram arguments and pragma arguments. If the @strong{else} -clause is omitted, @strong{else} @emph{True} is assumed; +anyway, such as subprogram arguments and pragma arguments. If the `else' +clause is omitted, `else' `True' is assumed; thus @code{(if A then B)} is a way to conveniently represent -@emph{(A implies B)} in standard logic. +`(A implies B)' in standard logic. RM References: 4.03.03 (15) 4.04 (1) 4.04 (7) 4.05.07 (0) 4.07 (2) 4.07 (3) 4.09 (12) 4.09 (33) 5.03 (3) 5.03 (4) 7.05 (2.1/2) @@ -27620,7 +27620,7 @@ RM References: 4.03.03 (15) 4.04 (1) 4.04 (7) 4.05.07 (0) 4.07 (2) @itemize * @item -@emph{AI-0037 Out-of-range box associations in aggregate (0000-00-00)} +`AI-0037 Out-of-range box associations in aggregate (0000-00-00)' This AI confirms that an association of the form @code{Indx => <>} in an array aggregate must raise @code{Constraint_Error} if @code{Indx} @@ -27637,7 +27637,7 @@ RM References: 4.03.03 (29) @itemize * @item -@emph{AI-0123 Composability of equality (2010-04-13)} +`AI-0123 Composability of equality (2010-04-13)' Equality of untagged record composes, so that the predefined equality for a composite type that includes a component of some untagged record type @@ -27663,7 +27663,7 @@ RM References: 4.05.02 (9.7/2) 4.05.02 (14) 4.05.02 (15) 4.05.02 (24) @itemize * @item -@emph{AI-0088 The value of exponentiation (0000-00-00)} +`AI-0088 The value of exponentiation (0000-00-00)' This AI clarifies the equivalence rule given for the dynamic semantics of exponentiation: the value of the operation can be obtained by repeated @@ -27680,7 +27680,7 @@ RM References: 4.05.06 (11) @itemize * @item -@emph{AI-0188 Case expressions (2010-01-09)} +`AI-0188 Case expressions (2010-01-09)' Case expressions are permitted. This allows use of constructs such as: @@ -27697,11 +27697,11 @@ RM References: 4.05.07 (0) 4.05.08 (0) 4.09 (12) 4.09 (33) @itemize * @item -@emph{AI-0104 Null exclusion and uninitialized allocator (2010-07-15)} +`AI-0104 Null exclusion and uninitialized allocator (2010-07-15)' The assignment @code{Ptr := new not null Some_Ptr;} will raise @code{Constraint_Error} because the default value of the allocated object is -@strong{null}. This useless construct is illegal in Ada 2012. +`null'. This useless construct is illegal in Ada 2012. RM References: 4.08 (2) @end itemize @@ -27712,7 +27712,7 @@ RM References: 4.08 (2) @itemize * @item -@emph{AI-0157 Allocation/Deallocation from empty pool (2010-07-11)} +`AI-0157 Allocation/Deallocation from empty pool (2010-07-11)' Allocation and Deallocation from an empty storage pool (i.e. allocation or deallocation of a pointer for which a static storage size clause of zero @@ -27728,7 +27728,7 @@ RM References: 4.08 (5.3/2) 13.11.02 (4) 13.11.02 (17) @itemize * @item -@emph{AI-0179 Statement not required after label (2010-04-10)} +`AI-0179 Statement not required after label (2010-04-10)' It is not necessary to have a statement following a label, so a label can appear at the end of a statement sequence without the need for putting a @@ -27744,7 +27744,7 @@ RM References: 5.01 (2) @itemize * @item -@emph{AI-0139-2 Syntactic sugar for iterators (2010-09-29)} +`AI-0139-2 Syntactic sugar for iterators (2010-09-29)' The new syntax for iterating over arrays and containers is now implemented. Iteration over containers is for now limited to read-only iterators. Only @@ -27759,7 +27759,7 @@ RM References: 5.05 @itemize * @item -@emph{AI-0134 Profiles must match for full conformance (0000-00-00)} +`AI-0134 Profiles must match for full conformance (0000-00-00)' For full conformance, the profiles of anonymous-access-to-subprogram parameters must match. GNAT has always enforced this rule. @@ -27773,7 +27773,7 @@ RM References: 6.03.01 (18) @itemize * @item -@emph{AI-0207 Mode conformance and access constant (0000-00-00)} +`AI-0207 Mode conformance and access constant (0000-00-00)' This AI confirms that access_to_constant indication must match for mode conformance. This was implemented in GNAT when the qualifier was originally @@ -27788,7 +27788,7 @@ RM References: 6.03.01 (16/2) @itemize * @item -@emph{AI-0046 Null exclusion match for full conformance (2010-07-17)} +`AI-0046 Null exclusion match for full conformance (2010-07-17)' For full conformance, in the case of access parameters, the null exclusion must match (either both or neither must have @code{not null}). @@ -27802,7 +27802,7 @@ RM References: 6.03.02 (18) @itemize * @item -@emph{AI-0118 The association of parameter associations (0000-00-00)} +`AI-0118 The association of parameter associations (0000-00-00)' This AI clarifies the rules for named associations in subprogram calls and generic instantiations. The rules have been in place since Ada 83. @@ -27816,7 +27816,7 @@ RM References: 6.04.01 (2) 12.03 (9) @itemize * @item -@emph{AI-0196 Null exclusion tests for out parameters (0000-00-00)} +`AI-0196 Null exclusion tests for out parameters (0000-00-00)' Null exclusion checks are not made for @code{out} parameters when evaluating the actual parameters. GNAT has never generated these checks. @@ -27830,9 +27830,9 @@ RM References: 6.04.01 (13) @itemize * @item -@emph{AI-0015 Constant return objects (0000-00-00)} +`AI-0015 Constant return objects (0000-00-00)' -The return object declared in an @emph{extended_return_statement} may be +The return object declared in an `extended_return_statement' may be declared constant. This was always intended, and GNAT has always allowed it. RM References: 6.05 (2.1/2) 3.03 (10/2) 3.03 (21) 6.05 (5/2) @@ -27845,7 +27845,7 @@ RM References: 6.05 (2.1/2) 3.03 (10/2) 3.03 (21) 6.05 (5/2) @itemize * @item -@emph{AI-0032 Extended return for class-wide functions (0000-00-00)} +`AI-0032 Extended return for class-wide functions (0000-00-00)' If a function returns a class-wide type, the object of an extended return statement can be declared with a specific type that is covered by the class- @@ -27863,7 +27863,7 @@ RM References: 6.05 (5.2/2) 6.05 (5.3/2) 6.05 (5.6/2) 6.05 (5.8/2) @itemize * @item -@emph{AI-0103 Static matching for extended return (2010-07-23)} +`AI-0103 Static matching for extended return (2010-07-23)' If the return subtype of a function is an elementary type or a constrained type, the subtype indication in an extended return statement must match @@ -27878,7 +27878,7 @@ RM References: 6.05 (5.2/2) @itemize * @item -@emph{AI-0058 Abnormal completion of an extended return (0000-00-00)} +`AI-0058 Abnormal completion of an extended return (0000-00-00)' The RM had some incorrect wording implying wrong treatment of abnormal completion in an extended return. GNAT has always implemented the intended @@ -27893,7 +27893,7 @@ RM References: 6.05 (22/2) @itemize * @item -@emph{AI-0050 Raising Constraint_Error early for function call (0000-00-00)} +`AI-0050 Raising Constraint_Error early for function call (0000-00-00)' The implementation permissions for raising @code{Constraint_Error} early on a function call when it was clear an exception would be raised were over-permissive and allowed @@ -27909,7 +27909,7 @@ RM References: 6.05 (24/2) @itemize * @item -@emph{AI-0125 Nonoverridable operations of an ancestor (2010-09-28)} +`AI-0125 Nonoverridable operations of an ancestor (2010-09-28)' In Ada 2012, the declaration of a primitive operation of a type extension or private extension can also override an inherited primitive that is not @@ -27924,7 +27924,7 @@ RM References: 7.03.01 (6) 8.03 (23) 8.03.01 (5/2) 8.03.01 (6/2) @itemize * @item -@emph{AI-0062 Null exclusions and deferred constants (0000-00-00)} +`AI-0062 Null exclusions and deferred constants (0000-00-00)' A full constant may have a null exclusion even if its associated deferred constant does not. GNAT has always allowed this. @@ -27938,7 +27938,7 @@ RM References: 7.04 (6/2) 7.04 (7.1/2) @itemize * @item -@emph{AI-0178 Incomplete views are limited (0000-00-00)} +`AI-0178 Incomplete views are limited (0000-00-00)' This AI clarifies the role of incomplete views and plugs an omission in the RM. GNAT always correctly restricted the use of incomplete views and types. @@ -27952,7 +27952,7 @@ RM References: 7.05 (3/2) 7.05 (6/2) @itemize * @item -@emph{AI-0087 Actual for formal nonlimited derived type (2010-07-15)} +`AI-0087 Actual for formal nonlimited derived type (2010-07-15)' The actual for a formal nonlimited derived type cannot be limited. In particular, a formal derived type that extends a limited interface but which @@ -27967,7 +27967,7 @@ RM References: 7.05 (5/2) 12.05.01 (5.1/2) @itemize * @item -@emph{AI-0099 Tag determines whether finalization needed (0000-00-00)} +`AI-0099 Tag determines whether finalization needed (0000-00-00)' This AI clarifies that ‘needs finalization’ is part of dynamic semantics, and therefore depends on the run-time characteristics of an object (i.e. its @@ -27983,7 +27983,7 @@ RM References: 7.06.01 (6) 7.06.01 (7) 7.06.01 (8) 7.06.01 (9/2) @itemize * @item -@emph{AI-0064 Redundant finalization rule (0000-00-00)} +`AI-0064 Redundant finalization rule (0000-00-00)' This is an editorial change only. The intended behavior is already checked by an existing ACATS test, which GNAT has always executed correctly. @@ -27997,7 +27997,7 @@ RM References: 7.06.01 (17.1/1) @itemize * @item -@emph{AI-0026 Missing rules for Unchecked_Union (2010-07-07)} +`AI-0026 Missing rules for Unchecked_Union (2010-07-07)' Record representation clauses concerning Unchecked_Union types cannot mention the discriminant of the type. The type of a component declared in the variant @@ -28016,7 +28016,7 @@ RM References: 7.06 (9.4/2) B.03.03 (9/2) B.03.03 (10/2) @itemize * @item -@emph{AI-0205 Extended return declares visible name (0000-00-00)} +`AI-0205 Extended return declares visible name (0000-00-00)' This AI corrects a simple omission in the RM. Return objects have always been visible within an extended return statement. @@ -28030,7 +28030,7 @@ RM References: 8.03 (17) @itemize * @item -@emph{AI-0042 Overriding versus implemented-by (0000-00-00)} +`AI-0042 Overriding versus implemented-by (0000-00-00)' This AI fixes a wording gap in the RM. An operation of a synchronized interface can be implemented by a protected or task entry, but the abstract @@ -28047,7 +28047,7 @@ RM References: 9.01 (9.2/2) 9.04 (11.1/2) @itemize * @item -@emph{AI-0030 Requeue on synchronized interfaces (2010-07-19)} +`AI-0030 Requeue on synchronized interfaces (2010-07-19)' Requeue is permitted to a protected, synchronized or task interface primitive providing it is known that the overriding operation is an entry. Otherwise @@ -28066,7 +28066,7 @@ RM References: 9.05 (9) 9.05.04 (2) 9.05.04 (3) 9.05.04 (5) @itemize * @item -@emph{AI-0201 Independence of atomic object components (2010-07-22)} +`AI-0201 Independence of atomic object components (2010-07-22)' If an Atomic object has a pragma @code{Pack} or a @code{Component_Size} attribute, then individual components may not be addressable by independent @@ -28085,7 +28085,7 @@ RM References: 9.10 (1/3) C.06 (22/2) C.06 (23/2) @itemize * @item -@emph{AI-0009 Pragma Independent[_Components] (2010-07-23)} +`AI-0009 Pragma Independent[_Components] (2010-07-23)' This AI introduces the new pragmas @code{Independent} and @code{Independent_Components}, @@ -28102,7 +28102,7 @@ C.06 (4) C.06 (6) C.06 (9) C.06 (13) C.06 (14) @itemize * @item -@emph{AI-0072 Task signalling using ‘Terminated (0000-00-00)} +`AI-0072 Task signalling using ‘Terminated (0000-00-00)' This AI clarifies that task signalling for reading @code{'Terminated} only occurs if the result is True. GNAT semantics has always been consistent with @@ -28117,7 +28117,7 @@ RM References: 9.10 (6.1/1) @itemize * @item -@emph{AI-0108 Limited incomplete view and discriminants (0000-00-00)} +`AI-0108 Limited incomplete view and discriminants (0000-00-00)' This AI confirms that an incomplete type from a limited view does not have discriminants. This has always been the case in GNAT. @@ -28131,7 +28131,7 @@ RM References: 10.01.01 (12.3/2) @itemize * @item -@emph{AI-0129 Limited views and incomplete types (0000-00-00)} +`AI-0129 Limited views and incomplete types (0000-00-00)' This AI clarifies the description of limited views: a limited view of a package includes only one view of a type that has an incomplete declaration @@ -28148,7 +28148,7 @@ RM References: 10.01.01 (12.2/2) 10.01.01 (12.3/2) @itemize * @item -@emph{AI-0077 Limited withs and scope of declarations (0000-00-00)} +`AI-0077 Limited withs and scope of declarations (0000-00-00)' This AI clarifies that a declaration does not include a context clause, and confirms that it is illegal to have a context in which both a limited @@ -28164,7 +28164,7 @@ RM References: 10.01.02 (12/2) 10.01.02 (21/2) 10.01.02 (22/2) @itemize * @item -@emph{AI-0122 Private with and children of generics (0000-00-00)} +`AI-0122 Private with and children of generics (0000-00-00)' This AI clarifies the visibility of private children of generic units within instantiations of a parent. GNAT has always handled this correctly. @@ -28178,7 +28178,7 @@ RM References: 10.01.02 (12/2) @itemize * @item -@emph{AI-0040 Limited with clauses on descendant (0000-00-00)} +`AI-0040 Limited with clauses on descendant (0000-00-00)' This AI confirms that a limited with clause in a child unit cannot name an ancestor of the unit. This has always been checked in GNAT. @@ -28192,7 +28192,7 @@ RM References: 10.01.02 (20/2) @itemize * @item -@emph{AI-0132 Placement of library unit pragmas (0000-00-00)} +`AI-0132 Placement of library unit pragmas (0000-00-00)' This AI fills a gap in the description of library unit pragmas. The pragma clearly must apply to a library unit, even if it does not carry the name @@ -28207,7 +28207,7 @@ RM References: 10.01.05 (7) @itemize * @item -@emph{AI-0034 Categorization of limited views (0000-00-00)} +`AI-0034 Categorization of limited views (0000-00-00)' The RM makes certain limited with clauses illegal because of categorization considerations, when the corresponding normal with would be legal. This is @@ -28222,7 +28222,7 @@ RM References: 10.02.01 (11/1) 10.02.01 (17/2) @itemize * @item -@emph{AI-0035 Inconsistencies with Pure units (0000-00-00)} +`AI-0035 Inconsistencies with Pure units (0000-00-00)' This AI remedies some inconsistencies in the legality rules for Pure units. Derived access types are legal in a pure unit (on the assumption that the @@ -28239,7 +28239,7 @@ RM References: 10.02.01 (15.1/2) 10.02.01 (15.4/2) 10.02.01 (15.5/2) 10.0 @itemize * @item -@emph{AI-0219 Pure permissions and limited parameters (2010-05-25)} +`AI-0219 Pure permissions and limited parameters (2010-05-25)' This AI refines the rules for the cases with limited parameters which do not allow the implementations to omit ‘redundant’. GNAT now properly conforms @@ -28254,7 +28254,7 @@ RM References: 10.02.01 (18/2) @itemize * @item -@emph{AI-0043 Rules about raising exceptions (0000-00-00)} +`AI-0043 Rules about raising exceptions (0000-00-00)' This AI covers various omissions in the RM regarding the raising of exceptions. GNAT has always implemented the intended semantics. @@ -28268,7 +28268,7 @@ RM References: 11.04.01 (10.1/2) 11 (2) @itemize * @item -@emph{AI-0200 Mismatches in formal package declarations (0000-00-00)} +`AI-0200 Mismatches in formal package declarations (0000-00-00)' This AI plugs a gap in the RM which appeared to allow some obviously intended illegal instantiations. GNAT has never allowed these instantiations. @@ -28282,7 +28282,7 @@ RM References: 12.07 (16) @itemize * @item -@emph{AI-0112 Detection of duplicate pragmas (2010-07-24)} +`AI-0112 Detection of duplicate pragmas (2010-07-24)' This AI concerns giving names to various representation aspects, but the practical effect is simply to make the use of duplicate @@ -28300,7 +28300,7 @@ RM References: 13.01 (8) @itemize * @item -@emph{AI-0106 No representation pragmas on generic formals (0000-00-00)} +`AI-0106 No representation pragmas on generic formals (0000-00-00)' The RM appeared to allow representation pragmas on generic formal parameters, but this was not intended, and GNAT has never permitted this usage. @@ -28314,7 +28314,7 @@ RM References: 13.01 (9.1/1) @itemize * @item -@emph{AI-0012 Pack/Component_Size for aliased/atomic (2010-07-15)} +`AI-0012 Pack/Component_Size for aliased/atomic (2010-07-15)' It is now illegal to give an inappropriate component size or a pragma @code{Pack} that attempts to change the component size in the case of atomic @@ -28330,7 +28330,7 @@ RM References: 13.02 (6.1/2) 13.02 (7) C.06 (10) C.06 (11) C.06 (21) @itemize * @item -@emph{AI-0039 Stream attributes cannot be dynamic (0000-00-00)} +`AI-0039 Stream attributes cannot be dynamic (0000-00-00)' The RM permitted the use of dynamic expressions (such as @code{ptr.all})` for stream attributes, but these were never useful and are now illegal. GNAT @@ -28345,7 +28345,7 @@ RM References: 13.03 (4) 13.03 (6) 13.13.02 (38/2) @itemize * @item -@emph{AI-0095 Address of intrinsic subprograms (0000-00-00)} +`AI-0095 Address of intrinsic subprograms (0000-00-00)' The prefix of @code{'Address} cannot statically denote a subprogram with convention @code{Intrinsic}. The use of the @code{Address} attribute raises @@ -28361,7 +28361,7 @@ RM References: 13.03 (11/1) @itemize * @item -@emph{AI-0116 Alignment of class-wide objects (0000-00-00)} +`AI-0116 Alignment of class-wide objects (0000-00-00)' This AI requires that the alignment of a class-wide object be no greater than the alignment of any type in the class. GNAT has always followed this @@ -28376,7 +28376,7 @@ RM References: 13.03 (29) 13.11 (16) @itemize * @item -@emph{AI-0146 Type invariants (2009-09-21)} +`AI-0146 Type invariants (2009-09-21)' Type invariants may be specified for private types using the aspect notation. Aspect @code{Type_Invariant} may be specified for any private type, @@ -28385,7 +28385,7 @@ only be specified for tagged types, and is inherited by any descendent of the tagged types. The invariant is a boolean expression that is tested for being true in the following situations: conversions to the private type, object declarations for the private type that are default initialized, and -[@strong{in}] @strong{out} +[`in'] `out' parameters and returned result on return from any primitive operation for the type that is visible to a client. GNAT defines the synonyms @code{Invariant} for @code{Type_Invariant} and @@ -28400,7 +28400,7 @@ RM References: 13.03.03 (00) @itemize * @item -@emph{AI-0078 Relax Unchecked_Conversion alignment rules (0000-00-00)} +`AI-0078 Relax Unchecked_Conversion alignment rules (0000-00-00)' In Ada 2012, compilers are required to support unchecked conversion where the target alignment is a multiple of the source alignment. GNAT always supported @@ -28416,7 +28416,7 @@ RM References: 13.09 (7) @itemize * @item -@emph{AI-0195 Invalid value handling is implementation defined (2010-07-03)} +`AI-0195 Invalid value handling is implementation defined (2010-07-03)' The handling of invalid values is now designated to be implementation defined. This is a documentation change only, requiring Annex M in the GNAT @@ -28436,7 +28436,7 @@ RM References: 13.09.01 (10) @itemize * @item -@emph{AI-0193 Alignment of allocators (2010-09-16)} +`AI-0193 Alignment of allocators (2010-09-16)' This AI introduces a new attribute @code{Max_Alignment_For_Allocation}, analogous to @code{Max_Size_In_Storage_Elements}, but for alignment instead @@ -28452,7 +28452,7 @@ RM References: 13.11 (16) 13.11 (21) 13.11.01 (0) 13.11.01 (1) @itemize * @item -@emph{AI-0177 Parameterized expressions (2010-07-10)} +`AI-0177 Parameterized expressions (2010-07-10)' The new Ada 2012 notion of parameterized expressions is implemented. The form is: @@ -28474,7 +28474,7 @@ RM References: 13.11.01 (3/2) @itemize * @item -@emph{AI-0033 Attach/Interrupt_Handler in generic (2010-07-24)} +`AI-0033 Attach/Interrupt_Handler in generic (2010-07-24)' Neither of these two pragmas may appear within a generic template, because the generic might be instantiated at other than the library level. @@ -28488,7 +28488,7 @@ RM References: 13.11.02 (16) C.03.01 (7/2) C.03.01 (8/2) @itemize * @item -@emph{AI-0161 Restriction No_Default_Stream_Attributes (2010-09-11)} +`AI-0161 Restriction No_Default_Stream_Attributes (2010-09-11)' A new restriction @code{No_Default_Stream_Attributes} prevents the use of any of the default stream attributes for elementary types. If this restriction is @@ -28504,7 +28504,7 @@ RM References: 13.12.01 (4/2) 13.13.02 (40/2) 13.13.02 (52/2) @itemize * @item -@emph{AI-0194 Value of Stream_Size attribute (0000-00-00)} +`AI-0194 Value of Stream_Size attribute (0000-00-00)' The @code{Stream_Size} attribute returns the default number of bits in the stream representation of the given type. @@ -28521,7 +28521,7 @@ RM References: 13.13.02 (1.2/2) @itemize * @item -@emph{AI-0109 Redundant check in S’Class’Input (0000-00-00)} +`AI-0109 Redundant check in S’Class’Input (0000-00-00)' This AI is an editorial change only. It removes the need for a tag check that can never fail. @@ -28535,7 +28535,7 @@ RM References: 13.13.02 (34/2) @itemize * @item -@emph{AI-0007 Stream read and private scalar types (0000-00-00)} +`AI-0007 Stream read and private scalar types (0000-00-00)' The RM as written appeared to limit the possibilities of declaring read attribute procedures for private scalar types. This limitation was not @@ -28550,7 +28550,7 @@ RM References: 13.13.02 (50/2) 13.13.02 (51/2) @itemize * @item -@emph{AI-0065 Remote access types and external streaming (0000-00-00)} +`AI-0065 Remote access types and external streaming (0000-00-00)' This AI clarifies the fact that all remote access types support external streaming. This fixes an obvious oversight in the definition of the @@ -28565,7 +28565,7 @@ RM References: 13.13.02 (52/2) @itemize * @item -@emph{AI-0019 Freezing of primitives for tagged types (0000-00-00)} +`AI-0019 Freezing of primitives for tagged types (0000-00-00)' The RM suggests that primitive subprograms of a specific tagged type are frozen when the tagged type is frozen. This would be an incompatible change @@ -28581,7 +28581,7 @@ RM References: 13.14 (2) 13.14 (3/1) 13.14 (8.1/1) 13.14 (10) 13.14 (14 @itemize * @item -@emph{AI-0017 Freezing and incomplete types (0000-00-00)} +`AI-0017 Freezing and incomplete types (0000-00-00)' So-called ‘Taft-amendment types’ (i.e., types that are completed in package bodies) are not frozen by the occurrence of bodies in the @@ -28596,7 +28596,7 @@ RM References: 13.14 (3/1) @itemize * @item -@emph{AI-0060 Extended definition of remote access types (0000-00-00)} +`AI-0060 Extended definition of remote access types (0000-00-00)' This AI extends the definition of remote access types to include access to limited, synchronized, protected or task class-wide interface types. @@ -28611,7 +28611,7 @@ RM References: A (4) E.02.02 (9/1) E.02.02 (9.2/1) E.02.02 (14/2) E.02. @itemize * @item -@emph{AI-0114 Classification of letters (0000-00-00)} +`AI-0114 Classification of letters (0000-00-00)' The code points 170 (@code{FEMININE ORDINAL INDICATOR}), 181 (@code{MICRO SIGN}), and @@ -28630,7 +28630,7 @@ RM References: A.03.02 (59) A.04.06 (7) @itemize * @item -@emph{AI-0185 Ada.Wide_[Wide_]Characters.Handling (2010-07-06)} +`AI-0185 Ada.Wide_[Wide_]Characters.Handling (2010-07-06)' Two new packages @code{Ada.Wide_[Wide_]Characters.Handling} provide classification functions for @code{Wide_Character} and @@ -28647,7 +28647,7 @@ RM References: A.03.05 (0) A.03.06 (0) @itemize * @item -@emph{AI-0031 Add From parameter to Find_Token (2010-07-25)} +`AI-0031 Add From parameter to Find_Token (2010-07-25)' A new version of @code{Find_Token} is added to all relevant string packages, with an extra parameter @code{From}. Instead of starting at the first @@ -28667,7 +28667,7 @@ A.04.05 (46) @itemize * @item -@emph{AI-0056 Index on null string returns zero (0000-00-00)} +`AI-0056 Index on null string returns zero (0000-00-00)' The wording in the Ada 2005 RM implied an incompatible handling of the @code{Index} functions, resulting in raising an exception instead of @@ -28684,7 +28684,7 @@ RM References: A.04.03 (56.2/2) A.04.03 (58.5/2) @itemize * @item -@emph{AI-0137 String encoding package (2010-03-25)} +`AI-0137 String encoding package (2010-03-25)' The packages @code{Ada.Strings.UTF_Encoding}, together with its child packages, @code{Conversions}, @code{Strings}, @code{Wide_Strings}, @@ -28710,7 +28710,7 @@ RM References: A.04.11 @itemize * @item -@emph{AI-0038 Minor errors in Text_IO (0000-00-00)} +`AI-0038 Minor errors in Text_IO (0000-00-00)' These are minor errors in the description on three points. The intent on all these points has always been clear, and GNAT has always implemented the @@ -28725,7 +28725,7 @@ RM References: A.10.05 (37) A.10.07 (8/1) A.10.07 (10) A.10.07 (12) A.1 @itemize * @item -@emph{AI-0044 Restrictions on container instantiations (0000-00-00)} +`AI-0044 Restrictions on container instantiations (0000-00-00)' This AI places restrictions on allowed instantiations of generic containers. These restrictions are not checked by the compiler, so there is nothing to @@ -28740,7 +28740,7 @@ RM References: A.18 (4/2) A.18.02 (231/2) A.18.03 (145/2) A.18.06 (56/2) @itemize * @item -@emph{AI-0127 Adding Locale Capabilities (2010-09-29)} +`AI-0127 Adding Locale Capabilities (2010-09-29)' This package provides an interface for identifying the current locale. @@ -28754,7 +28754,7 @@ A.19.07 A.19.08 A.19.09 A.19.10 A.19.11 A.19.12 A.19.13 @itemize * @item -@emph{AI-0002 Export C with unconstrained arrays (0000-00-00)} +`AI-0002 Export C with unconstrained arrays (0000-00-00)' The compiler is not required to support exporting an Ada subprogram with convention C if there are parameters or a return type of an unconstrained @@ -28772,7 +28772,7 @@ RM References: B.01 (17) B.03 (62) B.03 (71.1/2) @itemize * @item -@emph{AI-0216 No_Task_Hierarchy forbids local tasks (0000-00-00)} +`AI-0216 No_Task_Hierarchy forbids local tasks (0000-00-00)' It is clearly the intention that @code{No_Task_Hierarchy} is intended to forbid tasks declared locally within subprograms, or functions returning task @@ -28789,7 +28789,7 @@ RM References: D.07 (3/3) @itemize * @item -@emph{AI-0211 No_Relative_Delays forbids Set_Handler use (2010-07-09)} +`AI-0211 No_Relative_Delays forbids Set_Handler use (2010-07-09)' The restriction @code{No_Relative_Delays} forbids any calls to the subprogram @code{Ada.Real_Time.Timing_Events.Set_Handler}. @@ -28803,12 +28803,12 @@ RM References: D.07 (5) D.07 (10/2) D.07 (10.4/2) D.07 (10.7/2) @itemize * @item -@emph{AI-0190 pragma Default_Storage_Pool (2010-09-15)} +`AI-0190 pragma Default_Storage_Pool (2010-09-15)' This AI introduces a new pragma @code{Default_Storage_Pool}, which can be used to control storage pools globally. In particular, you can force every access -type that is used for allocation (@strong{new}) to have an explicit storage pool, +type that is used for allocation (`new') to have an explicit storage pool, or you can declare a pool globally to be used for all access types that lack an explicit one. @@ -28821,7 +28821,7 @@ RM References: D.07 (8) @itemize * @item -@emph{AI-0189 No_Allocators_After_Elaboration (2010-01-23)} +`AI-0189 No_Allocators_After_Elaboration (2010-01-23)' This AI introduces a new restriction @code{No_Allocators_After_Elaboration}, which says that no dynamic allocation will occur once elaboration is @@ -28840,7 +28840,7 @@ RM References: D.07 (19.1/2) H.04 (23.3/2) @itemize * @item -@emph{AI-0171 Pragma CPU and Ravenscar Profile (2010-09-24)} +`AI-0171 Pragma CPU and Ravenscar Profile (2010-09-24)' A new package @code{System.Multiprocessors} is added, together with the definition of pragma @code{CPU} for controlling task affinity. A new no @@ -28856,7 +28856,7 @@ RM References: D.13.01 (4/2) D.16 @itemize * @item -@emph{AI-0210 Correct Timing_Events metric (0000-00-00)} +`AI-0210 Correct Timing_Events metric (0000-00-00)' This is a documentation only issue regarding wording of metric requirements, that does not affect the implementation of the compiler. @@ -28870,7 +28870,7 @@ RM References: D.15 (24/2) @itemize * @item -@emph{AI-0206 Remote types packages and preelaborate (2010-07-24)} +`AI-0206 Remote types packages and preelaborate (2010-07-24)' Remote types packages are now allowed to depend on preelaborated packages. This was formerly considered illegal. @@ -28884,7 +28884,7 @@ RM References: E.02.02 (6) @itemize * @item -@emph{AI-0152 Restriction No_Anonymous_Allocators (2010-09-08)} +`AI-0152 Restriction No_Anonymous_Allocators (2010-09-08)' Restriction @code{No_Anonymous_Allocators} prevents the use of allocators where the type of the returned value is an anonymous access type. @@ -28922,7 +28922,7 @@ change. GNAT can generate code to zero-out hardware registers before returning from a subprogram. -It can be enabled with the @code{-fzero-call-used-regs=@emph{choice}} +It can be enabled with the @code{-fzero-call-used-regs=`choice'} command-line option, to affect all subprograms in a compilation, and with a @code{Machine_Attribute} pragma, to affect only specific subprograms. @@ -28976,7 +28976,7 @@ pragma Machine_Attribute (Var, "strub"); -- scrubbing of the stack space used by that subprogram. @end example -There are also @code{-fstrub=@emph{choice}} command-line options to +There are also @code{-fstrub=`choice'} command-line options to control default settings. For usage and more details on the command-line options, on the @code{strub} attribute, and their use with other programming languages, see @cite{Using the GNU Compiler Collection (GCC)}. @@ -29447,7 +29447,7 @@ Ada 95 and later versions of the standard: @itemize * @item -@emph{Character literals} +`Character literals' Some uses of character literals are ambiguous. Since Ada 95 has introduced @code{Wide_Character} as a new predefined character type, some uses of @@ -29467,7 +29467,7 @@ for Char in Character range 'A' .. 'Z' loop ... end loop; @end example @item -@emph{New reserved words} +`New reserved words' The identifiers @code{abstract}, @code{aliased}, @code{protected}, @code{requeue}, @code{tagged}, and @code{until} are reserved in Ada 95. @@ -29475,7 +29475,7 @@ Existing Ada 83 code using any of these identifiers must be edited to use some alternative name. @item -@emph{Freezing rules} +`Freezing rules' The rules in Ada 95 are slightly different with regard to the point at which entities are frozen, and representation pragmas and clauses are @@ -29489,7 +29489,7 @@ cannot be applied to a subprogram body. If necessary, a separate subprogram declaration must be introduced to which the pragma can be applied. @item -@emph{Optional bodies for library packages} +`Optional bodies for library packages' In Ada 83, a package that did not require a package body was nevertheless allowed to have one. This lead to certain surprises in compiling large @@ -29506,7 +29506,7 @@ circularities) is to add an @code{Elaborate_Body} pragma to the package spec, since one effect of this pragma is to require the presence of a package body. @item -@emph{Numeric_Error is the same exception as Constraint_Error} +`Numeric_Error is the same exception as Constraint_Error' In Ada 95, the exception @code{Numeric_Error} is a renaming of @code{Constraint_Error}. This means that it is illegal to have separate exception handlers for @@ -29515,7 +29515,7 @@ the two exceptions. The fix is simply to remove the handler for the @code{Constraint_Error} in place of @code{Numeric_Error} in all cases). @item -@emph{Indefinite subtypes in generics} +`Indefinite subtypes in generics' In Ada 83, it was permissible to pass an indefinite type (e.g, @code{String}) as the actual for a generic formal private type, but then the instantiation @@ -29544,7 +29544,7 @@ the fix is usually simply to add the @code{(<>)} to the generic declaration. @itemize * @item -@emph{Conversions} +`Conversions' Conversions from real types to integer types round away from 0. In Ada 83 the conversion Integer(2.5) could deliver either 2 or 3 as its value. This @@ -29556,7 +29556,7 @@ Note, though, that this issue is no worse than already existed in Ada 83 when porting code from one vendor to another. @item -@emph{Tasking} +`Tasking' The Real-Time Annex introduces a set of policies that define the behavior of features that were implementation dependent in Ada 83, such as the order in @@ -29583,7 +29583,7 @@ situation that you should be alert to is the change in the predefined type @itemize * @item -@emph{Range of type `@w{`}Character`@w{`}} +`Range of type `@w{`}Character`@w{`}' The range of @code{Standard.Character} is now the full 256 characters of Latin-1, whereas in most Ada 83 implementations it was restricted @@ -29614,7 +29614,7 @@ covers only the restricted range. @itemize * @item -@emph{-gnat83} switch +`-gnat83' switch All implementations of GNAT provide a switch that causes GNAT to operate in Ada 83 mode. In this mode, some but not all compatibility problems @@ -29655,7 +29655,7 @@ for a complete description please see the @itemize * @item -@emph{New reserved words.} +`New reserved words.' The words @code{interface}, @code{overriding} and @code{synchronized} are reserved in Ada 2005. @@ -29663,7 +29663,7 @@ A pre-Ada 2005 program that uses any of these as an identifier will be illegal. @item -@emph{New declarations in predefined packages.} +`New declarations in predefined packages.' A number of packages in the predefined environment contain new declarations: @code{Ada.Exceptions}, @code{Ada.Real_Time}, @code{Ada.Strings}, @@ -29675,26 +29675,26 @@ If an Ada 95 program does a @code{with} and @code{use} of any of these packages, the new declarations may cause name clashes. @item -@emph{Access parameters.} +`Access parameters.' A nondispatching subprogram with an access parameter cannot be renamed as a dispatching operation. This was permitted in Ada 95. @item -@emph{Access types, discriminants, and constraints.} +`Access types, discriminants, and constraints.' Rule changes in this area have led to some incompatibilities; for example, constrained subtypes of some access types are not permitted in Ada 2005. @item -@emph{Aggregates for limited types.} +`Aggregates for limited types.' The allowance of aggregates for limited types in Ada 2005 raises the possibility of ambiguities in legal Ada 95 programs, since additional types now need to be considered in expression resolution. @item -@emph{Fixed-point multiplication and division.} +`Fixed-point multiplication and division.' Certain expressions involving ‘*’ or ‘/’ for a fixed-point type, which were legal in Ada 95 and invoked the predefined versions of these operations, @@ -29704,7 +29704,7 @@ expression, or by explicitly invoking the operation from package @code{Standard}. @item -@emph{Return-by-reference types.} +`Return-by-reference types.' The Ada 95 return-by-reference mechanism has been removed. Instead, the user can declare a function returning a value from an anonymous access type. @@ -29813,7 +29813,7 @@ elaboration problems) by implicitly inserting @code{Elaborate} or @code{Elaborate_All} pragmas where needed. However, this can lead to the creation of elaboration circularities and a resulting rejection of the program by gnatbind. This issue is -thoroughly described in the @emph{Elaboration Order Handling in GNAT} appendix +thoroughly described in the `Elaboration Order Handling in GNAT' appendix in the @cite{GNAT User’s Guide}. In brief, there are several ways to deal with this situation: @@ -29829,7 +29829,7 @@ elaboration-time code into explicitly-invoked procedures Constrain the elaboration order by including explicit @code{Elaborate_Body} or @code{Elaborate} pragmas, and then inhibit the generation of implicit @code{Elaborate_All} -pragmas either globally (as an effect of the @emph{-gnatE} switch) or locally +pragmas either globally (as an effect of the `-gnatE' switch) or locally (by selectively suppressing elaboration checks via pragma @code{Suppress(Elaboration_Check)} when it is safe to do so). @end itemize @@ -29869,7 +29869,7 @@ when other compilers appear.) @itemize * @item -@emph{Ada 83 Pragmas and Attributes} +`Ada 83 Pragmas and Attributes' Ada 95 compilers are allowed, but not required, to implement the missing Ada 83 pragmas and attributes that are no longer defined in Ada 95. @@ -29878,7 +29878,7 @@ a compatibility concern, but some other Ada 95 compilers reject these pragmas and attributes. @item -@emph{Specialized Needs Annexes} +`Specialized Needs Annexes' GNAT implements the full set of special needs annexes. At the current time, it is the only Ada 95 compiler to do so. This means that @@ -29886,7 +29886,7 @@ programs making use of these features may not be portable to other Ada 95 compilation systems. @item -@emph{Representation Clauses} +`Representation Clauses' Some other Ada 95 compilers implement only the minimal set of representation clauses required by the Ada 95 reference manual. GNAT goes @@ -29918,7 +29918,7 @@ the cases most likely to arise in existing Ada 83 code. @itemize * @item -@emph{Implicit Packing} +`Implicit Packing' Some Ada 83 compilers allowed a Size specification to cause implicit packing of an array or record. This could cause expensive implicit @@ -29934,7 +29934,7 @@ the explicit pragma @code{Pack}, or for more fine tuned control, provide a Component_Size clause. @item -@emph{Meaning of Size Attribute} +`Meaning of Size Attribute' The Size attribute in Ada 95 (and Ada 2005) for discrete types is defined as the minimal number of bits required to hold values of the type. For example, @@ -29947,7 +29947,7 @@ Object_Size can provide a useful way of duplicating the behavior of some Ada 83 compiler systems. @item -@emph{Size of Access Types} +`Size of Access Types' A common assumption in Ada 83 code is that an access type is in fact a pointer, and that therefore it will be the same size as a System.Address value. This @@ -30000,13 +30000,13 @@ applicable to GNAT. @itemize * @item -@emph{Default floating-point representation} +`Default floating-point representation' In GNAT, the default floating-point format is IEEE, whereas in HP Ada 83, it is VMS format. @item -@emph{System} +`System' the package System in GNAT exactly corresponds to the definition in the Ada 95 reference manual, which means that it excludes many of the @@ -30029,7 +30029,7 @@ Copyright 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -@strong{Preamble} +`Preamble' The purpose of this License is to make a manual, textbook, or other functional and useful document “free†in the sense of freedom: to @@ -30052,23 +30052,23 @@ it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. -@strong{1. APPLICABILITY AND DEFINITIONS} +`1. APPLICABILITY AND DEFINITIONS' This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that -work under the conditions stated herein. The @strong{Document}, below, +work under the conditions stated herein. The `Document', below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as “@strong{you}â€. You accept the license if you +licensee, and is addressed as “`you'â€. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. -A “@strong{Modified Version}†of the Document means any work containing the +A “`Modified Version'†of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. -A “@strong{Secondary Section}†is a named appendix or a front-matter section of +A “`Secondary Section'†is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly @@ -30079,7 +30079,7 @@ connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. -The “@strong{Invariant Sections}†are certain Secondary Sections whose titles +The “`Invariant Sections'†are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not @@ -30087,12 +30087,12 @@ allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. -The “@strong{Cover Texts}†are certain short passages of text that are listed, +The “`Cover Texts'†are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. -A “@strong{Transparent}†copy of the Document means a machine-readable copy, +A “`Transparent'†copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of @@ -30103,7 +30103,7 @@ to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount -of text. A copy that is not “Transparent†is called @strong{Opaque}. +of text. A copy that is not “Transparent†is called `Opaque'. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML @@ -30116,22 +30116,22 @@ processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. -The “@strong{Title Page}†means, for a printed book, the title page itself, +The “`Title Page'†means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page†means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. -The “@strong{publisher}†means any person or entity that distributes +The “`publisher'†means any person or entity that distributes copies of the Document to the public. -A section “@strong{Entitled XYZ}†means a named subunit of the Document whose +A section “`Entitled XYZ'†means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as “@strong{Acknowledgements}â€, -“@strong{Dedications}â€, “@strong{Endorsements}â€, or “@strong{History}â€.) -To “@strong{Preserve the Title}†+specific section name mentioned below, such as “`Acknowledgements'â€, +“`Dedications'â€, “`Endorsements'â€, or “`History'â€.) +To “`Preserve the Title'†of such a section when you modify the Document means that it remains a section “Entitled XYZ†according to this definition. @@ -30142,7 +30142,7 @@ License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. -@strong{2. VERBATIM COPYING} +`2. VERBATIM COPYING' You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the @@ -30157,7 +30157,7 @@ number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. -@strong{3. COPYING IN QUANTITY} +`3. COPYING IN QUANTITY' If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the @@ -30194,7 +30194,7 @@ It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. -@strong{4. MODIFICATIONS} +`4. MODIFICATIONS' You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release @@ -30311,7 +30311,7 @@ The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. -@strong{5. COMBINING DOCUMENTS} +`5. COMBINING DOCUMENTS' You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified @@ -30335,7 +30335,7 @@ in the various original documents, forming one section Entitled and any sections Entitled “Dedicationsâ€. You must delete all sections Entitled “Endorsementsâ€. -@strong{6. COLLECTIONS OF DOCUMENTS} +`6. COLLECTIONS OF DOCUMENTS' You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this @@ -30348,7 +30348,7 @@ it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. -@strong{7. AGGREGATION WITH INDEPENDENT WORKS} +`7. AGGREGATION WITH INDEPENDENT WORKS' A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or @@ -30367,7 +30367,7 @@ electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. -@strong{8. TRANSLATION} +`8. TRANSLATION' Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. @@ -30387,7 +30387,7 @@ If a section in the Document is Entitled “Acknowledgementsâ€, its Title (section 1) will typically require changing the actual title. -@strong{9. TERMINATION} +`9. TERMINATION' You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt @@ -30414,7 +30414,7 @@ this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. -@strong{10. FUTURE REVISIONS OF THIS LICENSE} +`10. FUTURE REVISIONS OF THIS LICENSE' The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new @@ -30435,7 +30435,7 @@ License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. -@strong{11. RELICENSING} +`11. RELICENSING' “Massive Multiauthor Collaboration Site†(or “MMC Siteâ€) means any World Wide Web server that publishes copyrightable works and also @@ -30464,7 +30464,7 @@ The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. -@strong{ADDENDUM: How to use this License for your documents} +`ADDENDUM: How to use this License for your documents' To use this License in a document you have written, include a copy of the License in the document and put the following copyright and diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 64ebd95..e1a4192a 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -3,7 +3,7 @@ @setfilename gnat_ugn.info @documentencoding UTF-8 @ifinfo -@*Generated by Sphinx 4.3.1.@* +@*Generated by Sphinx 5.1.1.@* @end ifinfo @settitle GNAT User's Guide for Native Platforms @defindex ge @@ -15,13 +15,11 @@ * gnat_ugn: (gnat_ugn.info). gnat_ugn @end direntry -@definfoenclose strong,`,' -@definfoenclose emph,`,' @c %**end of header @copying @quotation -GNAT User's Guide for Native Platforms , Jul 11, 2022 +GNAT User's Guide for Native Platforms , Aug 25, 2022 AdaCore @@ -48,7 +46,7 @@ Copyright @copyright{} 2008-2022, Free Software Foundation @c %**start of body @anchor{gnat_ugn doc}@anchor{0} -@emph{GNAT, The GNU Ada Development Environment} +`GNAT, The GNU Ada Development Environment' @include gcc-common.texi @@ -705,7 +703,7 @@ and @code{classes}. @code{Variables} @item -@emph{Emphasis} +`Emphasis' @item [optional information or parameters] @@ -939,15 +937,15 @@ following three separate files: @table @asis -@item @emph{greetings.ads} +@item `greetings.ads' spec of package @code{Greetings} -@item @emph{greetings.adb} +@item `greetings.adb' body of package @code{Greetings} -@item @emph{gmain.adb} +@item `gmain.adb' body of main program @end table @@ -1175,8 +1173,8 @@ code is used to represent the end of file. Each file contains a single Ada compilation unit, including any pragmas associated with the unit. For example, this means you must place a -package declaration (a package @emph{spec}) and the corresponding body in -separate files. An Ada @emph{compilation} (which is a sequence of +package declaration (a package `spec') and the corresponding body in +separate files. An Ada `compilation' (which is a sequence of compilation units) is represented using a sequence of files. Similarly, you will place each subunit or child unit in a separate file. @@ -1234,7 +1232,7 @@ GNAT also supports several other 8-bit coding schemes: @table @asis -@item @emph{ISO 8859-2 (Latin-2)} +@item `ISO 8859-2 (Latin-2)' Latin-2 letters allowed in identifiers, with uppercase and lowercase equivalence. @@ -1247,7 +1245,7 @@ equivalence. @table @asis -@item @emph{ISO 8859-3 (Latin-3)} +@item `ISO 8859-3 (Latin-3)' Latin-3 letters allowed in identifiers, with uppercase and lowercase equivalence. @@ -1260,7 +1258,7 @@ equivalence. @table @asis -@item @emph{ISO 8859-4 (Latin-4)} +@item `ISO 8859-4 (Latin-4)' Latin-4 letters allowed in identifiers, with uppercase and lowercase equivalence. @@ -1273,7 +1271,7 @@ equivalence. @table @asis -@item @emph{ISO 8859-5 (Cyrillic)} +@item `ISO 8859-5 (Cyrillic)' ISO 8859-5 letters (Cyrillic) allowed in identifiers, with uppercase and lowercase equivalence. @@ -1286,7 +1284,7 @@ lowercase equivalence. @table @asis -@item @emph{ISO 8859-15 (Latin-9)} +@item `ISO 8859-15 (Latin-9)' ISO 8859-15 (Latin-9) letters allowed in identifiers, with uppercase and lowercase equivalence @@ -1297,7 +1295,7 @@ lowercase equivalence @table @asis -@item @emph{IBM PC (code page 437)} +@item `IBM PC (code page 437)' This code page is the normal default for PCs in the U.S. It corresponds to the original IBM PC character set. This set has some, but not all, of @@ -1311,14 +1309,14 @@ identifiers with uppercase and lowercase equivalence. @table @asis -@item @emph{IBM PC (code page 850)} +@item `IBM PC (code page 850)' This code page is a modification of 437 extended to include all the Latin-1 letters, but still not with the usual Latin-1 encoding. In this mode, all these letters are allowed in identifiers with uppercase and lowercase equivalence. -@item @emph{Full Upper 8-bit} +@item `Full Upper 8-bit' Any character in the range 80-FF allowed in identifiers, and all are considered distinct. In other words, there are no uppercase and lowercase @@ -1326,7 +1324,7 @@ equivalences in this range. This is useful in conjunction with certain encoding schemes used for some foreign character sets (e.g., the typical method of representing Chinese characters on the PC). -@item @emph{No Upper-Half} +@item `No Upper-Half' No upper-half characters in the range 80-FF are allowed in identifiers. This gives Ada 83 compatibility for identifier names. @@ -1349,7 +1347,7 @@ possible encoding schemes: @table @asis -@item @emph{Hex Coding} +@item `Hex Coding' In this encoding, a wide character is represented by the following five character sequence: @@ -1364,7 +1362,7 @@ example, ESC A345 is used to represent the wide character with code @code{16#A345#}. This scheme is compatible with use of the full Wide_Character set. -@item @emph{Upper-Half Coding} +@item `Upper-Half Coding' @geindex Upper-Half Coding @@ -1375,7 +1373,7 @@ character, but is not required to be in the upper half. This method can be also used for shift-JIS or EUC, where the internal coding matches the external coding. -@item @emph{Shift JIS Coding} +@item `Shift JIS Coding' @geindex Shift JIS Coding @@ -1387,7 +1385,7 @@ character according to the standard algorithm for Shift-JIS conversion. Only characters defined in the JIS code set table can be used with this encoding method. -@item @emph{EUC Coding} +@item `EUC Coding' @geindex EUC Coding @@ -1398,7 +1396,7 @@ character code is the corresponding JIS character according to the EUC encoding algorithm. Only characters defined in the JIS code set table can be used with this encoding method. -@item @emph{UTF-8 Coding} +@item `UTF-8 Coding' A wide character is represented using UCS Transformation Format 8 (UTF-8) as defined in Annex R of ISO @@ -1419,7 +1417,7 @@ other wide characters are represented as sequences of upper-half 6-byte sequences, and in the following section on wide wide characters, the use of these sequences is documented). -@item @emph{Brackets Coding} +@item `Brackets Coding' In this encoding, a wide character is represented by the following eight character sequence: @@ -1460,7 +1458,7 @@ possible encoding schemes: @table @asis -@item @emph{UTF-8 Coding} +@item `UTF-8 Coding' A wide character is represented using UCS Transformation Format 8 (UTF-8) as defined in Annex R of ISO @@ -1480,7 +1478,7 @@ is a four, five, or six byte sequence: where the @code{xxx} bits correspond to the left-padded bits of the 32-bit character value. -@item @emph{Brackets Coding} +@item `Brackets Coding' In this encoding, a wide wide character is represented by the following ten or twelve byte character sequence: @@ -1971,7 +1969,7 @@ Display Copyright and version, then exit disregarding all other options. If @code{--version} was not used, display usage, then exit disregarding all other options. -@item @code{--subdirs=@emph{dir}} +@item @code{--subdirs=`dir'} Real object, library or exec directories are subdirectories <dir> of the specified ones. @@ -1990,7 +1988,7 @@ Start another section of directories/patterns. @table @asis -@item @code{-c@emph{filename}} +@item @code{-c`filename'} Create a configuration pragmas file @code{filename} (instead of the default @code{gnat.adc}). @@ -2007,7 +2005,7 @@ specified, no switch @code{-P} may be specified (see below). @table @asis -@item @code{-d@emph{dir}} +@item @code{-d`dir'} Look for source files in directory @code{dir}. There may be zero, one or more spaces between @code{-d} and @code{dir}. @@ -2035,7 +2033,7 @@ specified with switch @code{-d} must exist and be readable. @table @asis -@item @code{-D@emph{filename}} +@item @code{-D`filename'} Look for source files in all directories listed in text file @code{filename}. There may be zero, one or more spaces between @code{-D} @@ -2052,7 +2050,7 @@ Follow symbolic links when processing project files. @geindex -f (gnatname) -@item @code{-f@emph{pattern}} +@item @code{-f`pattern'} Foreign patterns. Using this switch, it is possible to add sources of languages other than Ada to the list of sources of a project file. @@ -2075,7 +2073,7 @@ Output usage (help) information. The output is written to @code{stdout}. @geindex -P (gnatname) -@item @code{-P@emph{proj}} +@item @code{-P`proj'} Create or update project file @code{proj}. There may be zero, one or more space between @code{-P} and @code{proj}. @code{proj} may include directory @@ -2112,7 +2110,7 @@ the Naming Patterns, an indication is given that there is no match. @geindex -x (gnatname) -@item @code{-x@emph{pattern}} +@item @code{-x`pattern'} Excluded patterns. Using this switch, it is possible to exclude some files that would match the name patterns. For example, @@ -2202,7 +2200,7 @@ and GNAT, which use the prefixes respectively. @end itemize -The @code{-gnatk@emph{nn}} +The @code{-gnatk`nn'} switch of the compiler activates a ‘krunching’ circuit that limits file names to nn characters (where nn is a decimal integer). @@ -2611,10 +2609,10 @@ Causes @code{gnatchop} to operate in compilation mode, in which configuration pragmas are handled according to strict RM rules. See previous section for a full description of this mode. -@item @code{-gnat@emph{xxx}} +@item @code{-gnat`xxx'} -This passes the given @code{-gnat@emph{xxx}} switch to @code{gnat} which is -used to parse the given file. Not all @emph{xxx} options make sense, +This passes the given @code{-gnat`xxx'} switch to @code{gnat} which is +used to parse the given file. Not all `xxx' options make sense, but for example, the use of @code{-gnati2} allows @code{gnatchop} to process a source file that uses Latin-2 coding for identifiers. @@ -2629,7 +2627,7 @@ output file showing usage information. @table @asis -@item @code{-k@emph{mm}} +@item @code{-k`mm'} Limit generated file names to the specified number @code{mm} of characters. @@ -2732,7 +2730,7 @@ units to be skipped. @table @asis -@item @code{--GCC=@emph{xxxx}} +@item @code{--GCC=`xxxx'} Specify the path of the GNAT parser to be used. When this switch is used, no attempt is made to add the prefix to the GNAT parser executable. @@ -2904,7 +2902,7 @@ the type of restriction. Restrictions that require partition-wide consistency (like @code{No_Tasking}) are recognized wherever they appear -and can be freely inherited, e.g. from a @emph{with}ed unit to the @emph{with}ing +and can be freely inherited, e.g. from a `with'ed unit to the `with'ing unit. This makes sense since the binder will in any case insist on seeing consistent use, so any unit not conforming to any restrictions that are anywhere in the partition will be rejected, and you might as well find @@ -2945,7 +2943,7 @@ configuration pragmas, or more conveniently by direct editing of the Besides @code{gnat.adc}, additional files containing configuration pragmas may be applied to the current compilation using the switch -@code{-gnatec=@emph{path}} where @code{path} must designate an existing file that +@code{-gnatec=`path'} where @code{path} must designate an existing file that contains only configuration pragmas. These configuration pragmas are in addition to those found in @code{gnat.adc} (provided @code{gnat.adc} is present and switch @code{-gnatA} is not used). @@ -3060,10 +3058,10 @@ additional source files as follows: @itemize * @item -If a file being compiled @emph{with}s a unit @code{X}, the object file +If a file being compiled `with's a unit @code{X}, the object file depends on the file containing the spec of unit @code{X}. This includes -files that are @emph{with}ed implicitly either because they are parents -of @emph{with}ed child units or they are run-time units required by the +files that are `with'ed implicitly either because they are parents +of `with'ed child units or they are run-time units required by the language constructs used in a particular unit. @item @@ -3117,7 +3115,7 @@ The object file for a parent unit depends on all its subunit body files. The previous two rules meant that for purposes of computing dependencies and recompilation, a body and all its subunits are treated as an indivisible whole. -These rules are applied transitively: if unit @code{A} @emph{with}s +These rules are applied transitively: if unit @code{A} `with's unit @code{B}, whose elaboration calls an inlined procedure in package @code{C}, the object file for unit @code{A} will depend on the body of @code{C}, in file @code{c.adb}. @@ -3179,7 +3177,7 @@ checking. Categorization information (e.g., use of pragma @code{Pure}). @item -Information on all @emph{with}ed units, including presence of +Information on all `with'ed units, including presence of @code{Elaborate} or @code{Elaborate_All} pragmas. @item @@ -3249,8 +3247,8 @@ object files for the Ada units of the program. This section describes how to build and use libraries with GNAT, and also shows how to recompile the GNAT run-time library. You should be familiar with the -Project Manager facility (see the @emph{GNAT_Project_Manager} chapter of the -@emph{GPRbuild User’s Guide}) before reading this chapter. +Project Manager facility (see the `GNAT_Project_Manager' chapter of the +`GPRbuild User’s Guide') before reading this chapter. @menu * Introduction to Libraries in GNAT:: @@ -3299,14 +3297,14 @@ documentation purposes. Alternatively, it may expose only the units needed by an external user to make use of the library. That is to say, the specs reflecting the library services along with all the units needed to compile those specs, which can include generic bodies or any body implementing an -inlined routine. In the case of @emph{stand-alone libraries} those exposed -units are called @emph{interface units} (@ref{6b,,Stand-alone Ada Libraries}). +inlined routine. In the case of `stand-alone libraries' those exposed +units are called `interface units' (@ref{6b,,Stand-alone Ada Libraries}). All compilation units comprising an application, including those in a library, need to be elaborated in an order partially defined by Ada’s semantics. GNAT computes the elaboration order from the @code{ALI} files and this is why they constitute a mandatory part of GNAT libraries. -@emph{Stand-alone libraries} are the exception to this rule because a specific +`Stand-alone libraries' are the exception to this rule because a specific library elaboration routine is produced independently of the application(s) using the library. @@ -3328,9 +3326,9 @@ using the library. The easiest way to build a library is to use the Project Manager, -which supports a special type of project called a @emph{Library Project} -(see the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User’s Guide}). +which supports a special type of project called a `Library Project' +(see the `Library Projects' section in the `GNAT Project Manager' +chapter of the `GPRbuild User’s Guide'). A project is considered a library project, when two project-level attributes are defined in it: @code{Library_Name} and @code{Library_Dir}. In order to @@ -3451,9 +3449,9 @@ $ rm *.o $ chmod -w *.ali @end example -Please note that the library must have a name of the form @code{lib@emph{xxx}.a} -or @code{lib@emph{xxx}.so} (or @code{lib@emph{xxx}.dll} on Windows) in order to -be accessed by the directive @code{-l@emph{xxx}} at link time. +Please note that the library must have a name of the form @code{lib`xxx'.a} +or @code{lib`xxx'.so} (or @code{lib`xxx'.dll} on Windows) in order to +be accessed by the directive @code{-l`xxx'} at link time. @node Installing a library,Using a library,Building a library,General Ada Libraries @anchor{gnat_ugn/the_gnat_compilation_model id39}@anchor{71}@anchor{gnat_ugn/the_gnat_compilation_model installing-a-library}@anchor{72} @@ -3465,8 +3463,8 @@ be accessed by the directive @code{-l@emph{xxx}} at link time. @geindex GPR_PROJECT_PATH If you use project files, library installation is part of the library build -process (see the @emph{Installing a Library with Project Files} section of the -@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}). +process (see the `Installing a Library with Project Files' section of the +`GNAT Project Manager' chapter of the `GPRbuild User’s Guide'). When project files are not an option, it is also possible, but not recommended, to install the library so that the sources needed to use the library are on the @@ -3519,7 +3517,7 @@ any part of it. Once again, the project facility greatly simplifies the use of libraries. In this context, using a library is just a matter of adding a -@emph{with} clause in the user project. For instance, to make use of the +`with' clause in the user project. For instance, to make use of the library @code{My_Lib} shown in examples in earlier sections, you can write: @@ -3532,7 +3530,7 @@ end My_Proj; Even if you have a third-party, non-Ada library, you can still use GNAT’s Project Manager facility to provide a wrapper for it. For example, the -following project, when @emph{with}ed by your main project, will link with the +following project, when `with'ed by your main project, will link with the third-party library @code{liba.a}: @example @@ -3662,12 +3660,12 @@ main routine is not written in Ada. GNAT’s Project facility provides a simple way of building and installing -stand-alone libraries; see the @emph{Stand-alone Library Projects} section -in the @emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}. +stand-alone libraries; see the `Stand-alone Library Projects' section +in the `GNAT Project Manager' chapter of the `GPRbuild User’s Guide'. To be a Stand-alone Library Project, in addition to the two attributes that make a project a Library Project (@code{Library_Name} and -@code{Library_Dir}; see the @emph{Library Projects} section in the -@emph{GNAT Project Manager} chapter of the @emph{GPRbuild User’s Guide}), +@code{Library_Dir}; see the `Library Projects' section in the +`GNAT Project Manager' chapter of the `GPRbuild User’s Guide'), the attribute @code{Library_Interface} must be defined. For example: @example @@ -4054,7 +4052,7 @@ end Config; The @code{Config} package exists in multiple forms for the various targets, with an appropriate script selecting the version of @code{Config} needed. -Then any other unit requiring conditional compilation can do a @emph{with} +Then any other unit requiring conditional compilation can do a `with' of @code{Config} to make the constants visible. @node Debugging - A Special Case,Conditionalizing Declarations,Use of Boolean Constants,Modeling Conditional Compilation in Ada @@ -4445,7 +4443,7 @@ For further discussion of conditional compilation in general, see @subsubsection Preprocessing Symbols -Preprocessing symbols are defined in @emph{definition files} and referenced in the +Preprocessing symbols are defined in `definition files' and referenced in the sources to be preprocessed. A preprocessing symbol is an identifier, following normal Ada (case-insensitive) rules for its syntax, with the restriction that all characters need to be in the ASCII set (no accented letters). @@ -4470,7 +4468,7 @@ where @table @asis -@item @emph{switches} +@item `switches' is an optional sequence of switches as described in the next section. @end table @@ -4479,7 +4477,7 @@ is an optional sequence of switches as described in the next section. @table @asis -@item @emph{infile} +@item `infile' is the full name of the input file, which is an Ada source file containing preprocessor directives. @@ -4489,7 +4487,7 @@ file containing preprocessor directives. @table @asis -@item @emph{outfile} +@item `outfile' is the full name of the output file, which is an Ada source in standard Ada form. When used with GNAT, this file name will @@ -4580,7 +4578,7 @@ this context since comments are ignored by the compiler in any case). @table @asis -@item @code{-D@emph{symbol}[=@emph{value}]} +@item @code{-D`symbol'[=`value']} Defines a new preprocessing symbol with the specified value. If no value is given on the command line, then symbol is considered to be @code{True}. This switch @@ -4830,7 +4828,7 @@ As noted above, a file to be preprocessed consists of Ada source code in which preprocessing lines have been inserted. However, instead of using @code{gnatprep} to explicitly preprocess a file as a separate step before compilation, you can carry out the preprocessing implicitly -as part of compilation. Such @emph{integrated preprocessing}, which is the common +as part of compilation. Such `integrated preprocessing', which is the common style with C, is performed when either or both of the following switches are passed to the compiler: @@ -4840,7 +4838,7 @@ are passed to the compiler: @itemize * @item -@code{-gnatep}, which specifies the @emph{preprocessor data file}. +@code{-gnatep}, which specifies the `preprocessor data file'. This file dictates how the source files will be preprocessed (e.g., which symbol definition files apply to which sources). @@ -4869,7 +4867,7 @@ When using project files: @item the builder switch @code{-x} should be used if any Ada source is compiled with @code{gnatep=}, so that the compiler finds the -@emph{preprocessor data file}. +`preprocessor data file'. @item the preprocessing data file and the symbol definition files should be @@ -4891,7 +4889,7 @@ that relate to integrated preprocessing. @table @asis -@item @code{-gnatep=@emph{preprocessor_data_file}} +@item @code{-gnatep=`preprocessor_data_file'} This switch specifies the file name (without directory information) of the preprocessor data file. Either place this file @@ -4911,12 +4909,12 @@ end Prj; @end example @end quotation -A preprocessor data file is a text file that contains @emph{preprocessor -control lines}. A preprocessor control line directs the preprocessing of +A preprocessor data file is a text file that contains `preprocessor +control lines'. A preprocessor control line directs the preprocessing of either a particular source file, or, analogous to @code{others} in Ada, all sources not specified elsewhere in the preprocessor data file. A preprocessor control line -can optionally identify a @emph{definition file} that assigns values to +can optionally identify a `definition file' that assigns values to preprocessor symbols, as well as a list of switches that relate to preprocessing. Empty lines and comments (using Ada syntax) are also permitted, with no @@ -5007,7 +5005,7 @@ Causes both preprocessor lines and the lines deleted by preprocessing to be retained as comments marked with the special string ‘@cite{–!}’. -@item @code{-D@emph{symbol}=@emph{new_value}} +@item @code{-D`symbol'=`new_value'} Define or redefine @code{symbol} to have @code{new_value} as its value. The permitted form for @code{symbol} is either an Ada identifier, or any Ada reserved word @@ -5036,7 +5034,7 @@ a @code{#if} or @code{#elsif} test will be treated as an error. @table @asis -@item @code{-gnateD@emph{symbol}[=@emph{new_value}]} +@item @code{-gnateD`symbol'[=`new_value']} Define or redefine @code{symbol} to have @code{new_value} as its value. If no value is supplied, then the value of @code{symbol} is @code{True}. @@ -5533,7 +5531,7 @@ The return type must be the same as the type of the first argument. The size of this type can only be 8, 16, 32, or 64. @item -Binary arithmetic operators: ‘+’, ‘-‘, ‘*’, ‘/’. +Binary arithmetic operators: ‘+’, ‘-’, ‘*’, ‘/’. The corresponding operator declaration must have parameters and result type that have the same root numeric type (for example, all three are long_float types). This simplifies the definition of operations that use type checking @@ -6461,7 +6459,7 @@ If you want to generate a single Ada file and not the transitive closure, you can use instead the @code{-fdump-ada-spec-slim} switch. You can optionally specify a parent unit, of which all generated units will -be children, using @code{-fada-spec-parent=@emph{unit}}. +be children, using @code{-fada-spec-parent=`unit'}. The simple @code{gcc}-based command works only for C headers. For C++ headers you need to use either the @code{g++} command or the combination @code{gcc -x c++}. @@ -6502,7 +6500,7 @@ $ gcc -c -fdump-ada-spec readline1.h Generating bindings for C++ headers is done using the same options, always -with the @emph{g++} compiler. Note that generating Ada spec from C++ headers is a +with the `g++' compiler. Note that generating Ada spec from C++ headers is a much more complex job and support for C++ headers is much more limited that support for C headers. As a result, you will need to modify the resulting bindings by hand more extensively when using C++ headers. @@ -6510,7 +6508,7 @@ bindings by hand more extensively when using C++ headers. In this mode, C++ classes will be mapped to Ada tagged types, constructors will be mapped using the @code{CPP_Constructor} pragma, and when possible, multiple inheritance of abstract classes will be mapped to Ada interfaces -(see the @emph{Interfacing to C++} section in the @cite{GNAT Reference Manual} +(see the `Interfacing to C++' section in the @cite{GNAT Reference Manual} for additional information on interfacing to C++). For example, given the following C++ header file: @@ -6629,7 +6627,7 @@ only. @table @asis -@item @code{-fada-spec-parent=@emph{unit}} +@item @code{-fada-spec-parent=`unit'} Specifies that all files generated by @code{-fdump-ada-spec} are to be child units of the specified parent unit. @@ -6780,7 +6778,7 @@ used for Ada 83. The GNAT model of compilation is close to the C and C++ models. You can think of Ada specs as corresponding to header files in C. As in C, you don’t need to compile specs; they are compiled when they are used. The -Ada @emph{with} is similar in effect to the @code{#include} of a C +Ada `with' is similar in effect to the @code{#include} of a C header. One notable difference is that, in Ada, you may compile specs separately @@ -6830,7 +6828,7 @@ previously compiled. In particular: @itemize * @item -When a unit is @emph{with}ed, the unit seen by the compiler corresponds +When a unit is `with'ed, the unit seen by the compiler corresponds to the version of the unit most recently compiled into the library. @item @@ -6849,7 +6847,7 @@ files can affect the results of a compilation. In particular: @itemize * @item -When a unit is @emph{with}ed, the unit seen by the compiler corresponds +When a unit is `with'ed, the unit seen by the compiler corresponds to the source version of the unit that is currently accessible to the compiler. @@ -7042,8 +7040,8 @@ dependencies, they will always be tracked exactly correctly by @code{gnatmake}. Note that for advanced forms of project structure, we recommend creating -a project file as explained in the @emph{GNAT_Project_Manager} chapter in the -@emph{GPRbuild User’s Guide}, and using the +a project file as explained in the `GNAT_Project_Manager' chapter in the +`GPRbuild User’s Guide', and using the @code{gprbuild} tool which supports building with project files and works similarly to @code{gnatmake}. @@ -7125,7 +7123,7 @@ all other options. @table @asis -@item @code{-P@emph{project}} +@item @code{-P`project'} Build GNAT project file @code{project} using GPRbuild. When this switch is present, all other command-line switches are treated as GPRbuild switches @@ -7140,7 +7138,7 @@ and not @code{gnatmake} switches. @table @asis -@item @code{--GCC=@emph{compiler_name}} +@item @code{--GCC=`compiler_name'} Program used for compiling. The default is @code{gcc}. You need to use quotes around @code{compiler_name} if @code{compiler_name} contains @@ -7163,7 +7161,7 @@ all the additional switches are also taken into account. Thus, @table @asis -@item @code{--GNATBIND=@emph{binder_name}} +@item @code{--GNATBIND=`binder_name'} Program used for binding. The default is @code{gnatbind}. You need to use quotes around @code{binder_name} if @code{binder_name} contains spaces @@ -7181,7 +7179,7 @@ itself must not include any embedded spaces. @table @asis -@item @code{--GNATLINK=@emph{linker_name}} +@item @code{--GNATLINK=`linker_name'} Program used for linking. The default is @code{gnatlink}. You need to use quotes around @code{linker_name} if @code{linker_name} contains spaces @@ -7198,7 +7196,7 @@ itself must not include any embedded spaces. When linking an executable, create a map file. The name of the map file has the same name as the executable with extension “.mapâ€. -@item @code{--create-map-file=@emph{mapfile}} +@item @code{--create-map-file=`mapfile'} When linking an executable, create a map file with the specified name. @end table @@ -7210,7 +7208,7 @@ When linking an executable, create a map file with the specified name. @item @code{--create-missing-dirs} -When using project files (@code{-P@emph{project}}), automatically create +When using project files (@code{-P`project'}), automatically create missing object directories, library directories and exec directories. @@ -7219,7 +7217,7 @@ directories. Disallow simultaneous compilations in the same object directory when project files are used. -@item @code{--subdirs=@emph{subdir}} +@item @code{--subdirs=`subdir'} Actual object directory of each project file is the subdirectory subdir of the object directory specified or defaulted in the project file. @@ -7230,7 +7228,7 @@ By default, shared library projects are not allowed to import static library projects. When this switch is used on the command line, this restriction is relaxed. -@item @code{--source-info=@emph{source info file}} +@item @code{--source-info=`source info file'} Specify a source info file. This switch is active only when project files are used. If the source info file is specified as a relative path, then it is @@ -7341,7 +7339,7 @@ will add any newly accessed sources to the mapping file. @table @asis -@item @code{-C=@emph{file}} +@item @code{-C=`file'} Use a specific mapping file. The file, specified as a path name (absolute or relative) by this switch, should already exist, otherwise the switch is @@ -7373,7 +7371,7 @@ the compiler. These lines are displayed even in quiet output mode. @table @asis -@item @code{-D @emph{dir}} +@item @code{-D `dir'} Put all object files and ALI file in directory @code{dir}. If the @code{-D} switch is not used, all object files @@ -7387,7 +7385,7 @@ This switch cannot be used when using a project file. @table @asis -@item @code{-eI@emph{nnn}} +@item @code{-eI`nnn'} Indicates that the main source is a multi-unit source and the rank of the unit in the source file is nnn. nnn needs to be a positive number and a valid @@ -7499,7 +7497,7 @@ object and ALI files in the directory where it found the dummy file. @table @asis -@item @code{-j@emph{n}} +@item @code{-j`n'} Use @code{n} processes to carry out the (re)compilations. On a multiprocessor machine compilations will occur in parallel. If @code{n} is 0, then the @@ -7591,7 +7589,7 @@ is typically what you want. If you also specify the @code{-a} switch, dependencies of the GNAT internal files are also listed. Note that dependencies of the objects in external Ada libraries (see -switch @code{-aL@emph{dir}} in the following list) +switch @code{-aL`dir'} in the following list) are never reported. @end table @@ -7614,7 +7612,7 @@ file, will eventually result in recompiling all required units. @table @asis -@item @code{-o @emph{exec_name}} +@item @code{-o `exec_name'} Output executable name. The name of the final executable program will be @code{exec_name}. If the @code{-o} switch is omitted the default @@ -7732,7 +7730,7 @@ Verbosity level Medium. Potentially display fewer lines than in verbosity High. Verbosity level High. Equivalent to -v. -@item @code{-vP@emph{x}} +@item @code{-vP`x'} Indicate the verbosity of the parsing of GNAT project files. See @ref{cf,,Switches Related to Project Files}. @@ -7754,7 +7752,7 @@ be those specified on the command line. Even when @code{-x} is used, mains specified on the command line need to be sources of a project file. -@item @code{-X@emph{name}=@emph{value}} +@item @code{-X`name'=`value'} Indicate that external variable @code{name} has the value @code{value}. The Project Manager will use this value for occurrences of @@ -7789,7 +7787,7 @@ is passed to @code{gcc} (e.g., @code{-O}, @code{-gnato,} etc.) @table @asis -@item @code{-aI@emph{dir}} +@item @code{-aI`dir'} When looking for source files also look in directory @code{dir}. The order in which source files search is undertaken is @@ -7801,7 +7799,7 @@ described in @ref{73,,Search Paths and the Run-Time Library (RTL)}. @table @asis -@item @code{-aL@emph{dir}} +@item @code{-aL`dir'} Consider @code{dir} as being an externally provided Ada library. Instructs @code{gnatmake} to skip compilation units whose @code{.ALI} @@ -7809,7 +7807,7 @@ files have been located in directory @code{dir}. This allows you to have missing bodies for the units in @code{dir} and to ignore out of date bodies for the same units. You still need to specify the location of the specs for these units by using the switches -@code{-aI@emph{dir}} or @code{-I@emph{dir}}. +@code{-aI`dir'} or @code{-I`dir'}. Note: this switch is provided for compatibility with previous versions of @code{gnatmake}. The easier method of causing standard libraries to be excluded from consideration is to write-protect the corresponding @@ -7821,7 +7819,7 @@ ALI files. @table @asis -@item @code{-aO@emph{dir}} +@item @code{-aO`dir'} When searching for library and object files, look in directory @code{dir}. The order in which library files are searched is described in @@ -7836,15 +7834,15 @@ When searching for library and object files, look in directory @table @asis -@item @code{-A@emph{dir}} +@item @code{-A`dir'} -Equivalent to @code{-aL@emph{dir}} @code{-aI@emph{dir}}. +Equivalent to @code{-aL`dir'} @code{-aI`dir'}. @geindex -I (gnatmake) -@item @code{-I@emph{dir}} +@item @code{-I`dir'} -Equivalent to @code{-aO@emph{dir} -aI@emph{dir}}. +Equivalent to @code{-aO`dir' -aI`dir'}. @end table @geindex -I- (gnatmake) @@ -7870,11 +7868,11 @@ where @code{gnatmake} was invoked. @table @asis -@item @code{-L@emph{dir}} +@item @code{-L`dir'} Add directory @code{dir} to the list of directories in which the linker will search for libraries. This is equivalent to -@code{-largs} @code{-L@emph{dir}}. +@code{-largs} @code{-L`dir'}. Furthermore, under Windows, the sources pointed to by the libraries path set in the registry are not searched for. @end table @@ -7904,7 +7902,7 @@ Do not look for library files in the system default directory. @table @asis -@item @code{--RTS=@emph{rts-path}} +@item @code{--RTS=`rts-path'} Specifies the default location of the run-time library. GNAT looks for the run-time @@ -7916,13 +7914,13 @@ in the following directories, and stops as soon as a valid run-time is found @itemize * @item -@emph{<current directory>/$rts_path} +`<current directory>/$rts_path' @item -@emph{<default-search-dir>/$rts_path} +`<default-search-dir>/$rts_path' @item -@emph{<default-search-dir>/rts-$rts_path} +`<default-search-dir>/rts-$rts_path' @item The selected path is handled like a normal RTS path. @@ -7946,7 +7944,7 @@ designated component of GNAT. @table @asis -@item @code{-cargs @emph{switches}} +@item @code{-cargs `switches'} Compiler switches. Here @code{switches} is a list of switches that are valid switches for @code{gcc}. They will be passed on to @@ -7958,7 +7956,7 @@ all compile steps performed by @code{gnatmake}. @table @asis -@item @code{-bargs @emph{switches}} +@item @code{-bargs `switches'} Binder switches. Here @code{switches} is a list of switches that are valid switches for @code{gnatbind}. They will be passed on to @@ -7970,7 +7968,7 @@ all bind steps performed by @code{gnatmake}. @table @asis -@item @code{-largs @emph{switches}} +@item @code{-largs `switches'} Linker switches. Here @code{switches} is a list of switches that are valid switches for @code{gnatlink}. They will be passed on to @@ -7982,7 +7980,7 @@ all link steps performed by @code{gnatmake}. @table @asis -@item @code{-margs @emph{switches}} +@item @code{-margs `switches'} Make switches. The switches are directly interpreted by @code{gnatmake}, regardless of any previous occurrence of @code{-cargs}, @code{-bargs} @@ -8034,9 +8032,9 @@ unless @code{-a} is also specified. @item @code{gnatmake} has been designed to make the use of Ada libraries particularly convenient. Assume you have an Ada library organized -as follows: @emph{obj-dir} contains the objects and ALI files for +as follows: `obj-dir' contains the objects and ALI files for of your Ada compilation units, -whereas @emph{include-dir} contains the +whereas `include-dir' contains the specs of these units, but no bodies. Then to compile a unit stored in @code{main.adb}, which uses this Ada library you would just type: @@ -8070,7 +8068,7 @@ it may be useful to have some basic understanding of the @code{gnatmake} approach and in particular to understand how it uses the results of previous compilations without incorrectly depending on them. -First a definition: an object file is considered @emph{up to date} if the +First a definition: an object file is considered `up to date' if the corresponding ALI file exists and if all the source files listed in the dependency section of this ALI file have time stamps matching those in the ALI file. This means that neither the source file itself nor any @@ -8114,13 +8112,13 @@ by @code{gnatmake}. It may be necessary to use the switch @table @asis -@item @emph{gnatmake hello.adb} +@item `gnatmake hello.adb' Compile all files necessary to bind and link the main program @code{hello.adb} (containing unit @code{Hello}) and bind and link the resulting object files to generate an executable file @code{hello}. -@item @emph{gnatmake main1 main2 main3} +@item `gnatmake main1 main2 main3' Compile all files necessary to bind and link the main programs @code{main1.adb} (containing unit @code{Main1}), @code{main2.adb} @@ -8129,7 +8127,7 @@ Compile all files necessary to bind and link the main programs to generate three executable files @code{main1}, @code{main2} and @code{main3}. -@item @emph{gnatmake -q Main_Unit -cargs -O2 -bargs -l} +@item `gnatmake -q Main_Unit -cargs -O2 -bargs -l' Compile all files necessary to bind and link the main program unit @code{Main_Unit} (from file @code{main_unit.adb}). All compilations will @@ -8180,7 +8178,7 @@ the body file (@code{.adb}) for a library level package or generic package that has a body @end itemize -You need @emph{not} compile the following files +You need `not' compile the following files @itemize * @@ -8242,7 +8240,7 @@ two output files in the current directory, but you may specify a source file in any directory using an absolute or relative path specification containing the directory information. -TESTING: the @code{--foobar@emph{NN}} switch +TESTING: the @code{--foobar`NN'} switch @geindex gnat1 @@ -8407,7 +8405,7 @@ file directly. @item When you compile a unit, the source files for the specs of all units -that it @emph{with}s, all its subunits, and the bodies of any generics it +that it `with's, all its subunits, and the bodies of any generics it instantiates must be available (reachable by the search-paths mechanism described above), or you will receive a fatal error message. @end itemize @@ -8489,7 +8487,7 @@ compilation units. @table @asis -@item @code{-b @emph{target}} +@item @code{-b `target'} Compile your program to run on @code{target}, which is the name of a system configuration. You must have a GNAT cross-compiler built if @@ -8501,7 +8499,7 @@ system configuration. You must have a GNAT cross-compiler built if @table @asis -@item @code{-B@emph{dir}} +@item @code{-B`dir'} Load compiler executables (for example, @code{gnat1}, the Ada compiler) from @code{dir} instead of the default location. Only use this switch @@ -8587,7 +8585,7 @@ emitted in the debug information. @table @asis -@item @code{-flto[=@emph{n}]} +@item @code{-flto[=`n']} Enables Link Time Optimization. This switch must be used in conjunction with the @code{-Ox} switches (but not with the @code{-gnatn} switch @@ -8978,7 +8976,7 @@ ALI files. @table @asis -@item @code{-gnatec=@emph{path}} +@item @code{-gnatec=`path'} Specify a configuration pragma file (the equal sign is optional) @@ -9012,7 +9010,7 @@ Disable atomic synchronization @table @asis -@item @code{-gnateDsymbol[=@emph{value}]} +@item @code{-gnateDsymbol[=`value']} Defines a symbol, associated with @code{value}, for preprocessing. (@ref{90,,Integrated Preprocessing}). @@ -9084,7 +9082,7 @@ Save result of preprocessing in a text file. @table @asis -@item @code{-gnatei@emph{nnn}} +@item @code{-gnatei`nnn'} Set maximum number of instantiations during compilation of a single unit to @code{nnn}. This may be useful in increasing the default maximum of 8000 for @@ -9096,7 +9094,7 @@ the rare case when a single unit legitimately exceeds this limit. @table @asis -@item @code{-gnateI@emph{nnn}} +@item @code{-gnateI`nnn'} Indicates that the source is a multi-unit source and that the index of the unit to compile is @code{nnn}. @code{nnn} needs to be a positive number and need @@ -9135,7 +9133,7 @@ This switch turns off the info messages about implicit elaboration pragmas. @table @asis -@item @code{-gnatem=@emph{path}} +@item @code{-gnatem=`path'} Specify a mapping file (the equal sign is optional) @@ -9147,7 +9145,7 @@ Specify a mapping file @table @asis -@item @code{-gnatep=@emph{file}} +@item @code{-gnatep=`file'} Specify a preprocessing data file (the equal sign is optional) @@ -9184,7 +9182,7 @@ Synonym of @code{-fdump-scos}, kept for backwards compatibility. @table @asis -@item @code{-gnatet=@emph{path}} +@item @code{-gnatet=`path'} Generate target dependent information. The format of the output file is described in the section about switch @code{-gnateT}. @@ -9195,7 +9193,7 @@ described in the section about switch @code{-gnateT}. @table @asis -@item @code{-gnateT=@emph{path}} +@item @code{-gnateT=`path'} Read target dependent information, such as endianness or sizes and alignments of base type. If this switch is passed, the default target dependent @@ -9449,7 +9447,7 @@ For further details see @ref{f,,Elaboration Order Handling in GNAT}. @table @asis -@item @code{-gnati@emph{c}} +@item @code{-gnati`c'} Identifier character set (@code{c} = 1/2/3/4/5/9/p/8/f/n/w). For details of the possible selections for @code{c}, @@ -9482,7 +9480,7 @@ code is likely to malfunction at run time. @table @asis -@item @code{-gnatj@emph{nn}} +@item @code{-gnatj`nn'} Reformat error messages to fit on @code{nn} character lines @end table @@ -9543,7 +9541,7 @@ details see @ref{f,,Elaboration Order Handling in GNAT}. @table @asis -@item @code{-gnatk=@emph{n}} +@item @code{-gnatk=`n'} Limit file names to @code{n} (1-999) characters (@code{k} = krunch). @end table @@ -9575,7 +9573,7 @@ source output. @table @asis -@item @code{-gnatm=@emph{n}} +@item @code{-gnatm=`n'} Limit number of detected error or warning messages to @code{n} where @code{n} is in the range 1..999999. The default setting if @@ -9656,7 +9654,7 @@ Interpretation @item -@emph{1} +`1' @tab @@ -9664,7 +9662,7 @@ All intermediate overflows checked against base type (@code{STRICT}) @item -@emph{2} +`2' @tab @@ -9672,7 +9670,7 @@ Minimize intermediate overflows (@code{MINIMIZED}) @item -@emph{3} +`3' @tab @@ -9795,7 +9793,7 @@ Print package Standard. @table @asis -@item @code{-gnatT@emph{nnn}} +@item @code{-gnatT`nnn'} All compiler tables start at @code{nnn} times usual starting size. @end table @@ -9845,7 +9843,7 @@ Control level of validity checking (@ref{e7,,Validity Checking}). @table @asis -@item @code{-gnatw@emph{xxx}} +@item @code{-gnatw`xxx'} Warning mode where @code{xxx} is a string of option letters that denotes @@ -9858,7 +9856,7 @@ are enabled or disabled (@ref{eb,,Warning Message Control}). @table @asis -@item @code{-gnatW@emph{e}} +@item @code{-gnatW`e'} Wide character encoding method (@code{e}=n/h/u/s/e/8). @@ -9899,7 +9897,7 @@ Enable built-in style checks (@ref{ec,,Style Checking}). @table @asis -@item @code{-gnatz@emph{m}} +@item @code{-gnatz`m'} Distribution stub generation and compilation (@code{m}=r/c for receiver/caller stubs). @@ -9910,7 +9908,7 @@ Distribution stub generation and compilation @table @asis -@item @code{-I@emph{dir}} +@item @code{-I`dir'} @geindex RTL @@ -9938,7 +9936,7 @@ files in the directory containing the source file named in the command line @table @asis -@item @code{-o @emph{file}} +@item @code{-o `file'} This switch is used in @code{gcc} to redirect the generated object file and its associated ALI file. Beware of this switch with GNAT, because it may @@ -9973,7 +9971,7 @@ Library (RTL) ALI files. @table @asis -@item @code{-O[@emph{n}]} +@item @code{-O[`n']} @code{n} controls the optimization level: @@ -9981,7 +9979,7 @@ Library (RTL) ALI files. @multitable {xxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @item -@emph{n} +`n' @tab @@ -9989,7 +9987,7 @@ Effect @item -@emph{0} +`0' @tab @@ -9997,7 +9995,7 @@ No optimization, the default setting if no @code{-O} appears @item -@emph{1} +`1' @tab @@ -10007,7 +10005,7 @@ time. @item -@emph{2} +`2' @tab @@ -10016,7 +10014,7 @@ the cost of substantially increased compilation time. @item -@emph{3} +`3' @tab @@ -10025,7 +10023,7 @@ subprograms in the same unit. @item -@emph{s} +`s' @tab @@ -10053,7 +10051,7 @@ exit status. @table @asis -@item @code{--RTS=@emph{rts-path}} +@item @code{--RTS=`rts-path'} Specifies the default location of the run-time library. Same meaning as the equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @@ -10102,7 +10100,7 @@ compiler you are executing. @table @asis -@item @code{-V @emph{ver}} +@item @code{-V `ver'} Execute @code{ver} version of the compiler. This is the @code{gcc} version, not the GNAT version. @@ -10301,7 +10299,7 @@ warning messages generated. @table @asis -@item @code{-gnatl=@emph{fname}} +@item @code{-gnatl=`fname'} This has the same effect as @code{-gnatl} except that the output is written to a file instead of to standard output. If the given name @@ -10345,7 +10343,7 @@ format message or full listing (which as usual is written to @table @asis -@item @code{-gnatm=@emph{n}} +@item @code{-gnatm=`n'} The @code{m} stands for maximum. @code{n} is a decimal integer in the @@ -10607,7 +10605,7 @@ Wrong length on string assignment Violations of style rules if style checking is enabled @item -Unused @emph{with} clauses +Unused `with' clauses @item @code{Bit_Order} usage that does not have any effect @@ -10622,7 +10620,7 @@ Dereference of possibly null value Declaration that is likely to cause storage error @item -Internal GNAT unit @emph{with}ed by application unit +Internal GNAT unit `with'ed by application unit @item Values known to be out of range at compile time @@ -10676,7 +10674,7 @@ of the pragma in the @cite{GNAT_Reference_manual}). @item @code{-gnatwa} -@emph{Activate most optional warnings.} +`Activate most optional warnings.' This switch activates most optional warning messages. See the remaining list in this section for details on optional warning messages that can be @@ -10751,7 +10749,7 @@ All other optional warnings are turned on. @item @code{-gnatwA} -@emph{Suppress all optional errors.} +`Suppress all optional errors.' This switch suppresses all optional warning messages, see remaining list in this section for details on optional warning messages that can be @@ -10773,7 +10771,7 @@ the warnings for implicit dereferencing. @item @code{-gnatw.a} -@emph{Activate warnings on failing assertions.} +`Activate warnings on failing assertions.' @geindex Assert failures @@ -10790,7 +10788,7 @@ generated. @item @code{-gnatw.A} -@emph{Suppress warnings on failing assertions.} +`Suppress warnings on failing assertions.' @geindex Assert failures @@ -10805,7 +10803,7 @@ compile time that the assertion will fail. @item @code{-gnatw_a} -@emph{Activate warnings on anonymous allocators.} +`Activate warnings on anonymous allocators.' @geindex Anonymous allocators @@ -10822,7 +10820,7 @@ RM 3.10.2 (14). @item @code{-gnatw_A} -@emph{Supress warnings on anonymous allocators.} +`Supress warnings on anonymous allocators.' @geindex Anonymous allocators @@ -10836,7 +10834,7 @@ This switch suppresses warnings for anonymous access type allocators. @item @code{-gnatwb} -@emph{Activate warnings on bad fixed values.} +`Activate warnings on bad fixed values.' @geindex Bad fixed values @@ -10860,7 +10858,7 @@ are not generated. @item @code{-gnatwB} -@emph{Suppress warnings on bad fixed values.} +`Suppress warnings on bad fixed values.' This switch suppresses warnings for static fixed-point expressions whose value is not an exact multiple of Small. @@ -10873,7 +10871,7 @@ value is not an exact multiple of Small. @item @code{-gnatw.b} -@emph{Activate warnings on biased representation.} +`Activate warnings on biased representation.' @geindex Biased representation @@ -10890,7 +10888,7 @@ to represent 10/11). The default is that such warnings are generated. @item @code{-gnatw.B} -@emph{Suppress warnings on biased representation.} +`Suppress warnings on biased representation.' This switch suppresses warnings for representation clauses that force the use of biased representation. @@ -10903,7 +10901,7 @@ of biased representation. @item @code{-gnatwc} -@emph{Activate warnings on conditionals.} +`Activate warnings on conditionals.' @geindex Conditionals @geindex constant @@ -10940,7 +10938,7 @@ This warning can also be turned on using @code{-gnatwa}. @item @code{-gnatwC} -@emph{Suppress warnings on conditionals.} +`Suppress warnings on conditionals.' This switch suppresses warnings for conditional expressions used in tests that are known to be True or False at compile time. @@ -10953,7 +10951,7 @@ tests that are known to be True or False at compile time. @item @code{-gnatw.c} -@emph{Activate warnings on missing component clauses.} +`Activate warnings on missing component clauses.' @geindex Component clause @geindex missing @@ -10971,7 +10969,7 @@ component for which no component clause is present. @item @code{-gnatw.C} -@emph{Suppress warnings on missing component clauses.} +`Suppress warnings on missing component clauses.' This switch suppresses warnings for record components that are missing a component clause in the situation described above. @@ -10984,7 +10982,7 @@ missing a component clause in the situation described above. @item @code{-gnatw_c} -@emph{Activate warnings on unknown condition in Compile_Time_Warning.} +`Activate warnings on unknown condition in Compile_Time_Warning.' @geindex Compile_Time_Warning @@ -11003,7 +11001,7 @@ The default is that such warnings are generated. @item @code{-gnatw_C} -@emph{Suppress warnings on unknown condition in Compile_Time_Warning.} +`Suppress warnings on unknown condition in Compile_Time_Warning.' This switch supresses warnings on a pragma Compile_Time_Warning or Compile_Time_Error whose condition has a value that is not @@ -11017,7 +11015,7 @@ known at compile time. @item @code{-gnatwd} -@emph{Activate warnings on implicit dereferencing.} +`Activate warnings on implicit dereferencing.' If this switch is set, then the use of a prefix of an access type in an indexed component, slice, or selected component without an @@ -11035,7 +11033,7 @@ warnings are not generated. @item @code{-gnatwD} -@emph{Suppress warnings on implicit dereferencing.} +`Suppress warnings on implicit dereferencing.' @geindex Implicit dereferencing @@ -11053,7 +11051,7 @@ indexed components, slices, and selected components. @item @code{-gnatw.d} -@emph{Activate tagging of warning and info messages.} +`Activate tagging of warning and info messages.' If this switch is set, then warning messages are tagged, with one of the following strings: @@ -11064,35 +11062,35 @@ following strings: @itemize - @item -@emph{[-gnatw?]} +`[-gnatw?]' Used to tag warnings controlled by the switch @code{-gnatwx} where x is a letter a-z. @item -@emph{[-gnatw.?]} +`[-gnatw.?]' Used to tag warnings controlled by the switch @code{-gnatw.x} where x is a letter a-z. @item -@emph{[-gnatel]} +`[-gnatel]' Used to tag elaboration information (info) messages generated when the static model of elaboration is used and the @code{-gnatel} switch is set. @item -@emph{[restriction warning]} +`[restriction warning]' Used to tag warning messages for restriction violations, activated by use of the pragma @code{Restriction_Warnings}. @item -@emph{[warning-as-error]} +`[warning-as-error]' Used to tag warning messages that have been converted to error messages by use of the pragma Warning_As_Error. Note that such warnings are prefixed by -the string “error: †rather than “warning: “. +the string “error: “ rather than “warning: “. @item -@emph{[enabled by default]} +`[enabled by default]' Used to tag all other warnings that are always given by default, unless -warnings are completely suppressed using pragma @emph{Warnings(Off)} or +warnings are completely suppressed using pragma `Warnings(Off)' or the switch @code{-gnatws}. @end itemize @end quotation @@ -11105,7 +11103,7 @@ the switch @code{-gnatws}. @item @code{-gnatw.D} -@emph{Deactivate tagging of warning and info messages messages.} +`Deactivate tagging of warning and info messages messages.' If this switch is set, then warning messages return to the default mode in which warnings and info messages are not tagged as described above for @@ -11122,7 +11120,7 @@ mode in which warnings and info messages are not tagged as described above for @item @code{-gnatwe} -@emph{Treat warnings and style checks as errors.} +`Treat warnings and style checks as errors.' This switch causes warning messages and style check messages to be treated as errors. @@ -11140,7 +11138,7 @@ are not treated as errors if this switch is present. @item @code{-gnatw.e} -@emph{Activate every optional warning.} +`Activate every optional warning.' @geindex Warnings @geindex activate every optional warning @@ -11164,7 +11162,7 @@ been specifically designed according to specialized coding rules. @item @code{-gnatwE} -@emph{Treat all run-time exception warnings as errors.} +`Treat all run-time exception warnings as errors.' This switch causes warning messages regarding errors that will be raised during run-time execution to be treated as errors. @@ -11177,7 +11175,7 @@ during run-time execution to be treated as errors. @item @code{-gnatwf} -@emph{Activate warnings on unreferenced formals.} +`Activate warnings on unreferenced formals.' @geindex Formals @geindex unreferenced @@ -11195,7 +11193,7 @@ default is that these warnings are not generated. @item @code{-gnatwF} -@emph{Suppress warnings on unreferenced formals.} +`Suppress warnings on unreferenced formals.' This switch suppresses warnings for unreferenced formal parameters. Note that the @@ -11211,7 +11209,7 @@ formals. @item @code{-gnatwg} -@emph{Activate warnings on unrecognized pragmas.} +`Activate warnings on unrecognized pragmas.' @geindex Pragmas @geindex unrecognized @@ -11230,7 +11228,7 @@ Manual requirement that such warnings appear). @item @code{-gnatwG} -@emph{Suppress warnings on unrecognized pragmas.} +`Suppress warnings on unrecognized pragmas.' This switch suppresses warnings for unrecognized pragmas. @end table @@ -11242,7 +11240,7 @@ This switch suppresses warnings for unrecognized pragmas. @item @code{-gnatw.g} -@emph{Warnings used for GNAT sources.} +`Warnings used for GNAT sources.' This switch sets the warning categories that are used by the standard GNAT style. Currently this is equivalent to @@ -11257,7 +11255,7 @@ but more warnings may be added in the future without advanced notice. @item @code{-gnatwh} -@emph{Activate warnings on hiding.} +`Activate warnings on hiding.' @geindex Hiding of Declarations @@ -11274,7 +11272,7 @@ code. The default is that warnings on hiding are not generated. @item @code{-gnatwH} -@emph{Suppress warnings on hiding.} +`Suppress warnings on hiding.' This switch suppresses warnings on hiding declarations. @end table @@ -11286,7 +11284,7 @@ This switch suppresses warnings on hiding declarations. @item @code{-gnatw.h} -@emph{Activate warnings on holes/gaps in records.} +`Activate warnings on holes/gaps in records.' @geindex Record Representation (gaps) @@ -11303,7 +11301,7 @@ should specify a contiguous layout, adding unused fill fields if needed. @item @code{-gnatw.H} -@emph{Suppress warnings on holes/gaps in records.} +`Suppress warnings on holes/gaps in records.' This switch suppresses warnings on component clauses in record representation clauses that leave holes (haps) in the record layout. @@ -11316,16 +11314,16 @@ representation clauses that leave holes (haps) in the record layout. @item @code{-gnatwi} -@emph{Activate warnings on implementation units.} +`Activate warnings on implementation units.' -This switch activates warnings for a @emph{with} of an internal GNAT +This switch activates warnings for a `with' of an internal GNAT implementation unit, defined as any unit from the @code{Ada}, @code{Interfaces}, @code{GNAT}, or @code{System} hierarchies that is not documented in either the Ada Reference Manual or the GNAT Programmer’s Reference Manual. Such units are intended only -for internal implementation purposes and should not be @emph{with}ed +for internal implementation purposes and should not be `with'ed by user programs. The default is that such warnings are generated @end table @@ -11336,9 +11334,9 @@ by user programs. The default is that such warnings are generated @item @code{-gnatwI} -@emph{Disable warnings on implementation units.} +`Disable warnings on implementation units.' -This switch disables warnings for a @emph{with} of an internal GNAT +This switch disables warnings for a `with' of an internal GNAT implementation unit. @end table @@ -11349,7 +11347,7 @@ implementation unit. @item @code{-gnatw.i} -@emph{Activate warnings on overlapping actuals.} +`Activate warnings on overlapping actuals.' This switch enables a warning on statically detectable overlapping actuals in a subprogram call, when one of the actuals is an in-out parameter, and the @@ -11363,7 +11361,7 @@ types of the actuals are not by-copy types. This warning is off by default. @item @code{-gnatw.I} -@emph{Disable warnings on overlapping actuals.} +`Disable warnings on overlapping actuals.' This switch disables warnings on overlapping actuals in a call. @end table @@ -11375,7 +11373,7 @@ This switch disables warnings on overlapping actuals in a call. @item @code{-gnatwj} -@emph{Activate warnings on obsolescent features (Annex J).} +`Activate warnings on obsolescent features (Annex J).' @geindex Features @geindex obsolescent @@ -11411,7 +11409,7 @@ Second, the restriction does flag uses of package @code{ASCII}. @item @code{-gnatwJ} -@emph{Suppress warnings on obsolescent features (Annex J).} +`Suppress warnings on obsolescent features (Annex J).' This switch disables warnings on use of obsolescent features. @end table @@ -11423,7 +11421,7 @@ This switch disables warnings on use of obsolescent features. @item @code{-gnatw.j} -@emph{Activate warnings on late declarations of tagged type primitives.} +`Activate warnings on late declarations of tagged type primitives.' This switch activates warnings on visible primitives added to a tagged type after deriving a private extension from it. @@ -11436,7 +11434,7 @@ tagged type after deriving a private extension from it. @item @code{-gnatw.J} -@emph{Suppress warnings on late declarations of tagged type primitives.} +`Suppress warnings on late declarations of tagged type primitives.' This switch suppresses warnings on visible primitives added to a tagged type after deriving a private extension from it. @@ -11449,7 +11447,7 @@ tagged type after deriving a private extension from it. @item @code{-gnatwk} -@emph{Activate warnings on variables that could be constants.} +`Activate warnings on variables that could be constants.' This switch activates warnings for variables that are initialized but never modified, and then could be declared constants. The default is that @@ -11463,7 +11461,7 @@ such warnings are not given. @item @code{-gnatwK} -@emph{Suppress warnings on variables that could be constants.} +`Suppress warnings on variables that could be constants.' This switch disables warnings on variables that could be declared constants. @end table @@ -11475,7 +11473,7 @@ This switch disables warnings on variables that could be declared constants. @item @code{-gnatw.k} -@emph{Activate warnings on redefinition of names in standard.} +`Activate warnings on redefinition of names in standard.' This switch activates warnings for declarations that declare a name that is defined in package Standard. Such declarations can be confusing, @@ -11492,7 +11490,7 @@ not included in this check. @item @code{-gnatw.K} -@emph{Suppress warnings on redefinition of names in standard.} +`Suppress warnings on redefinition of names in standard.' This switch disables warnings for declarations that declare a name that is defined in package Standard. @@ -11505,7 +11503,7 @@ is defined in package Standard. @item @code{-gnatwl} -@emph{Activate warnings for elaboration pragmas.} +`Activate warnings for elaboration pragmas.' @geindex Elaboration @geindex warnings @@ -11527,7 +11525,7 @@ are not generated. @item @code{-gnatwL} -@emph{Suppress warnings for elaboration pragmas.} +`Suppress warnings for elaboration pragmas.' This switch suppresses warnings for possible elaboration problems. @end table @@ -11539,7 +11537,7 @@ This switch suppresses warnings for possible elaboration problems. @item @code{-gnatw.l} -@emph{List inherited aspects.} +`List inherited aspects.' This switch causes the compiler to list inherited invariants, preconditions, and postconditions from Type_Invariant’Class, Invariant’Class, @@ -11553,7 +11551,7 @@ Pre’Class, and Post’Class aspects. Also list inherited subtype predicates. @item @code{-gnatw.L} -@emph{Suppress listing of inherited aspects.} +`Suppress listing of inherited aspects.' This switch suppresses listing of inherited aspects. @end table @@ -11565,7 +11563,7 @@ This switch suppresses listing of inherited aspects. @item @code{-gnatwm} -@emph{Activate warnings on modified but unreferenced variables.} +`Activate warnings on modified but unreferenced variables.' This switch activates warnings for variables that are assigned (using an initialization value or with one or more assignment statements) but @@ -11582,7 +11580,7 @@ The default is that these warnings are not given. @item @code{-gnatwM} -@emph{Disable warnings on modified but unreferenced variables.} +`Disable warnings on modified but unreferenced variables.' This switch disables warnings for variables that are assigned or initialized, but never read. @@ -11595,7 +11593,7 @@ initialized, but never read. @item @code{-gnatw.m} -@emph{Activate warnings on suspicious modulus values.} +`Activate warnings on suspicious modulus values.' This switch activates warnings for modulus values that seem suspicious. The cases caught are where the size is the same as the modulus (e.g. @@ -11615,7 +11613,7 @@ integers after wrap-around. The default is that these warnings are given. @item @code{-gnatw.M} -@emph{Disable warnings on suspicious modulus values.} +`Disable warnings on suspicious modulus values.' This switch disables warnings for suspicious modulus values. @end table @@ -11627,7 +11625,7 @@ This switch disables warnings for suspicious modulus values. @item @code{-gnatwn} -@emph{Set normal warnings mode.} +`Set normal warnings mode.' This switch sets normal warning mode, in which enabled warnings are issued and treated as warnings rather than errors. This is the default @@ -11648,7 +11646,7 @@ use of @code{-gnatg}. @item @code{-gnatw.n} -@emph{Activate warnings on atomic synchronization.} +`Activate warnings on atomic synchronization.' This switch actives warnings when an access to an atomic variable requires the generation of atomic synchronization code. These @@ -11662,7 +11660,7 @@ warnings are off by default. @item @code{-gnatw.N} -@emph{Suppress warnings on atomic synchronization.} +`Suppress warnings on atomic synchronization.' @geindex Atomic Synchronization @geindex warnings @@ -11681,7 +11679,7 @@ requires the generation of atomic synchronization code. @item @code{-gnatwo} -@emph{Activate warnings on address clause overlays.} +`Activate warnings on address clause overlays.' This switch activates warnings for possibly unintended initialization effects of defining address clauses that cause one variable to overlap @@ -11695,7 +11693,7 @@ another. The default is that such warnings are generated. @item @code{-gnatwO} -@emph{Suppress warnings on address clause overlays.} +`Suppress warnings on address clause overlays.' This switch suppresses warnings on possibly unintended initialization effects of defining address clauses that cause one variable to overlap @@ -11709,7 +11707,7 @@ another. @item @code{-gnatw.o} -@emph{Activate warnings on modified but unreferenced out parameters.} +`Activate warnings on modified but unreferenced out parameters.' This switch activates warnings for variables that are modified by using them as actuals for a call to a procedure with an out mode formal, where @@ -11729,7 +11727,7 @@ The default is that these warnings are not given. @item @code{-gnatw.O} -@emph{Disable warnings on modified but unreferenced out parameters.} +`Disable warnings on modified but unreferenced out parameters.' This switch suppresses warnings for variables that are modified by using them as actuals for a call to a procedure with an out mode formal, where @@ -11746,7 +11744,7 @@ the resulting assigned value is never read. @item @code{-gnatwp} -@emph{Activate warnings on ineffective pragma Inlines.} +`Activate warnings on ineffective pragma Inlines.' This switch activates warnings for failure of front end inlining (activated by @code{-gnatN}) to inline a particular call. There are @@ -11764,7 +11762,7 @@ separately, using the gcc switch -Winline. @item @code{-gnatwP} -@emph{Suppress warnings on ineffective pragma Inlines.} +`Suppress warnings on ineffective pragma Inlines.' This switch suppresses warnings on ineffective pragma Inlines. If the inlining mechanism cannot inline a call, it will simply ignore the @@ -11781,7 +11779,7 @@ request silently. @item @code{-gnatw.p} -@emph{Activate warnings on parameter ordering.} +`Activate warnings on parameter ordering.' This switch activates warnings for cases of suspicious parameter ordering when the list of arguments are all simple identifiers that @@ -11799,7 +11797,7 @@ default is that such warnings are not given. @item @code{-gnatw.P} -@emph{Suppress warnings on parameter ordering.} +`Suppress warnings on parameter ordering.' This switch suppresses warnings on cases of suspicious parameter ordering. @@ -11812,7 +11810,7 @@ ordering. @item @code{-gnatw_p} -@emph{Activate warnings for pedantic checks.} +`Activate warnings for pedantic checks.' This switch activates warnings for the failure of certain pedantic checks. The only case currently supported is a check that the subtype_marks given @@ -11828,7 +11826,7 @@ is that such warnings are not given. @item @code{-gnatw_P} -@emph{Suppress warnings for pedantic checks.} +`Suppress warnings for pedantic checks.' This switch suppresses warnings on violations of pedantic checks. @end table @@ -11843,7 +11841,7 @@ This switch suppresses warnings on violations of pedantic checks. @item @code{-gnatwq} -@emph{Activate warnings on questionable missing parentheses.} +`Activate warnings on questionable missing parentheses.' This switch activates warnings for cases where parentheses are not used and the result is potential ambiguity from a readers point of view. For example @@ -11862,7 +11860,7 @@ is that these warnings are given. @item @code{-gnatwQ} -@emph{Suppress warnings on questionable missing parentheses.} +`Suppress warnings on questionable missing parentheses.' This switch suppresses warnings for cases where the association is not clear and the use of parentheses is preferred. @@ -11878,7 +11876,7 @@ clear and the use of parentheses is preferred. @item @code{-gnatw.q} -@emph{Activate warnings on questionable layout of record types.} +`Activate warnings on questionable layout of record types.' This switch activates warnings for cases where the default layout of a record type, that is to say the layout of its components in textual @@ -11932,7 +11930,7 @@ The default is that these warnings are not given. @item @code{-gnatw.Q} -@emph{Suppress warnings on questionable layout of record types.} +`Suppress warnings on questionable layout of record types.' This switch suppresses warnings for cases where the default layout of a record type would very likely cause inefficiencies. @@ -11945,7 +11943,7 @@ a record type would very likely cause inefficiencies. @item @code{-gnatwr} -@emph{Activate warnings on redundant constructs.} +`Activate warnings on redundant constructs.' This switch activates warnings for redundant constructs. The following is the current list of constructs regarded as redundant: @@ -11993,7 +11991,7 @@ The default is that warnings for redundant constructs are not given. @item @code{-gnatwR} -@emph{Suppress warnings on redundant constructs.} +`Suppress warnings on redundant constructs.' This switch suppresses warnings for redundant constructs. @end table @@ -12005,7 +12003,7 @@ This switch suppresses warnings for redundant constructs. @item @code{-gnatw.r} -@emph{Activate warnings for object renaming function.} +`Activate warnings for object renaming function.' This switch activates warnings for an object renaming that renames a function call, which is equivalent to a constant declaration (as @@ -12020,7 +12018,7 @@ warnings are given. @item @code{-gnatw.R} -@emph{Suppress warnings for object renaming function.} +`Suppress warnings for object renaming function.' This switch suppresses warnings for object renaming function. @end table @@ -12032,7 +12030,7 @@ This switch suppresses warnings for object renaming function. @item @code{-gnatw_r} -@emph{Activate warnings for out-of-order record representation clauses.} +`Activate warnings for out-of-order record representation clauses.' This switch activates warnings for record representation clauses, if the order of component declarations, component clauses, @@ -12047,7 +12045,7 @@ The default is that these warnings are not given. @item @code{-gnatw_R} -@emph{Suppress warnings for out-of-order record representation clauses.} +`Suppress warnings for out-of-order record representation clauses.' @end table @geindex -gnatws (gcc) @@ -12057,7 +12055,7 @@ The default is that these warnings are not given. @item @code{-gnatws} -@emph{Suppress all warnings.} +`Suppress all warnings.' This switch completely suppresses the output of all warning messages from the GNAT front end, including @@ -12082,7 +12080,7 @@ handling of style check messages. @item @code{-gnatw.s} -@emph{Activate warnings on overridden size clauses.} +`Activate warnings on overridden size clauses.' This switch activates warnings on component clauses in record representation clauses where the length given overrides that @@ -12099,7 +12097,7 @@ component type. @item @code{-gnatw.S} -@emph{Suppress warnings on overridden size clauses.} +`Suppress warnings on overridden size clauses.' This switch suppresses warnings on component clauses in record representation clauses that override size clauses, and similar @@ -12119,7 +12117,7 @@ warnings when an array component size overrides a size clause. @item @code{-gnatwt} -@emph{Activate warnings for tracking of deleted conditional code.} +`Activate warnings for tracking of deleted conditional code.' This switch activates warnings for tracking of code in conditionals (IF and CASE statements) that is detected to be dead code which cannot be executed, and @@ -12134,7 +12132,7 @@ useful for detecting deactivated code in certified applications. @item @code{-gnatwT} -@emph{Suppress warnings for tracking of deleted conditional code.} +`Suppress warnings for tracking of deleted conditional code.' This switch suppresses warnings for tracking of deleted conditional code. @end table @@ -12146,7 +12144,7 @@ This switch suppresses warnings for tracking of deleted conditional code. @item @code{-gnatw.t} -@emph{Activate warnings on suspicious contracts.} +`Activate warnings on suspicious contracts.' This switch activates warnings on suspicious contracts. This includes warnings on suspicious postconditions (whether a pragma @code{Postcondition} or a @@ -12168,7 +12166,7 @@ warnings are generated. @item @code{-gnatw.T} -@emph{Suppress warnings on suspicious contracts.} +`Suppress warnings on suspicious contracts.' This switch suppresses warnings on suspicious contracts. @end table @@ -12180,22 +12178,22 @@ This switch suppresses warnings on suspicious contracts. @item @code{-gnatwu} -@emph{Activate warnings on unused entities.} +`Activate warnings on unused entities.' This switch activates warnings to be generated for entities that -are declared but not referenced, and for units that are @emph{with}ed +are declared but not referenced, and for units that are `with'ed and not referenced. In the case of packages, a warning is also generated if no entities in the package are referenced. This means that if a with’ed package is referenced but the only references are in @code{use} clauses or @code{renames} declarations, a warning is still generated. A warning is also generated -for a generic package that is @emph{with}ed but never instantiated. +for a generic package that is `with'ed but never instantiated. In the case where a package or subprogram body is compiled, and there -is a @emph{with} on the corresponding spec +is a `with' on the corresponding spec that is only referenced in the body, a warning is also generated, noting that the -@emph{with} can be moved to the body. The default is that +`with' can be moved to the body. The default is that such warnings are not generated. This switch also activates warnings on unreferenced formals (it includes the effect of @code{-gnatwf}). @@ -12208,7 +12206,7 @@ This switch also activates warnings on unreferenced formals @item @code{-gnatwU} -@emph{Suppress warnings on unused entities.} +`Suppress warnings on unused entities.' This switch suppresses warnings for unused entities and packages. It also turns off warnings on unreferenced formals (and thus includes @@ -12222,13 +12220,13 @@ the effect of @code{-gnatwF}). @item @code{-gnatw.u} -@emph{Activate warnings on unordered enumeration types.} +`Activate warnings on unordered enumeration types.' This switch causes enumeration types to be considered as conceptually unordered, unless an explicit pragma @code{Ordered} is given for the type. The effect is to generate warnings in clients that use explicit comparisons or subranges, since these constructs both treat objects of the type as -ordered. (A @emph{client} is defined as a unit that is other than the unit in +ordered. (A `client' is defined as a unit that is other than the unit in which the type is declared, or its body or subunits.) Please refer to the description of pragma @code{Ordered} in the @cite{GNAT Reference Manual} for further details. @@ -12242,7 +12240,7 @@ The default is that such warnings are not generated. @item @code{-gnatw.U} -@emph{Deactivate warnings on unordered enumeration types.} +`Deactivate warnings on unordered enumeration types.' This switch causes all enumeration types to be considered as ordered, so that no warnings are given for comparisons or subranges for any type. @@ -12257,7 +12255,7 @@ that no warnings are given for comparisons or subranges for any type. @item @code{-gnatwv} -@emph{Activate warnings on unassigned variables.} +`Activate warnings on unassigned variables.' This switch activates warnings for access to variables which may not be properly initialized. The default is that @@ -12278,7 +12276,7 @@ unless the relevant type fully initializes all components. @item @code{-gnatwV} -@emph{Suppress warnings on unassigned variables.} +`Suppress warnings on unassigned variables.' This switch suppresses warnings for access to variables which may not be properly initialized. @@ -12293,7 +12291,7 @@ may not be properly initialized. @item @code{-gnatw.v} -@emph{Activate info messages for non-default bit order.} +`Activate info messages for non-default bit order.' This switch activates messages (labeled “infoâ€, they are not warnings, just informational messages) about the effects of non-default bit-order @@ -12310,7 +12308,7 @@ exact consequences of using this feature. @item @code{-gnatw.V} -@emph{Suppress info messages for non-default bit order.} +`Suppress info messages for non-default bit order.' This switch suppresses information messages for the effects of specifying non-default bit order on record components with component clauses. @@ -12325,7 +12323,7 @@ non-default bit order on record components with component clauses. @item @code{-gnatww} -@emph{Activate warnings on wrong low bound assumption.} +`Activate warnings on wrong low bound assumption.' This switch activates warnings for indexing an unconstrained string parameter with a literal or S’Length. This is a case where the code is assuming that the @@ -12340,7 +12338,7 @@ passed). The default is that such warnings are generated. @item @code{-gnatwW} -@emph{Suppress warnings on wrong low bound assumption.} +`Suppress warnings on wrong low bound assumption.' This switch suppresses warnings for indexing an unconstrained string parameter with a literal or S’Length. Note that this warning can also be suppressed @@ -12363,7 +12361,7 @@ procedure K (S : String) is @item @code{-gnatw.w} -@emph{Activate warnings on Warnings Off pragmas.} +`Activate warnings on Warnings Off pragmas.' This switch activates warnings for use of @code{pragma Warnings (Off, entity)} where either the pragma is entirely useless (because it suppresses no @@ -12382,7 +12380,7 @@ The default is that these warnings are not given. @item @code{-gnatw.W} -@emph{Suppress warnings on unnecessary Warnings Off pragmas.} +`Suppress warnings on unnecessary Warnings Off pragmas.' This switch suppresses warnings for use of @code{pragma Warnings (Off, ...)}. @end table @@ -12396,7 +12394,7 @@ This switch suppresses warnings for use of @code{pragma Warnings (Off, ...)}. @item @code{-gnatwx} -@emph{Activate warnings on Export/Import pragmas.} +`Activate warnings on Export/Import pragmas.' This switch activates warnings on Export/Import pragmas when the compiler detects a possible conflict between the Ada and @@ -12414,7 +12412,7 @@ generated. @item @code{-gnatwX} -@emph{Suppress warnings on Export/Import pragmas.} +`Suppress warnings on Export/Import pragmas.' This switch suppresses warnings on Export/Import pragmas. The sense of this is that you are telling the compiler that @@ -12429,7 +12427,7 @@ should not complain at you. @item @code{-gnatw.x} -@emph{Activate warnings for No_Exception_Propagation mode.} +`Activate warnings for No_Exception_Propagation mode.' This switch activates warnings for exception usage when pragma Restrictions (No_Exception_Propagation) is in effect. Warnings are given for implicit or @@ -12439,7 +12437,7 @@ these warnings are given for units that contain exception handlers. @item @code{-gnatw.X} -@emph{Disable warnings for No_Exception_Propagation mode.} +`Disable warnings for No_Exception_Propagation mode.' This switch disables warnings for exception usage when pragma Restrictions (No_Exception_Propagation) is in effect. @@ -12454,7 +12452,7 @@ This switch disables warnings for exception usage when pragma Restrictions @item @code{-gnatwy} -@emph{Activate warnings for Ada compatibility issues.} +`Activate warnings for Ada compatibility issues.' For the most part, newer versions of Ada are upwards compatible with older versions. For example, Ada 2005 programs will almost @@ -12476,7 +12474,7 @@ was called Ada 0Y, hence the choice of character. @item @code{-gnatwY} -@emph{Disable warnings for Ada compatibility issues.} +`Disable warnings for Ada compatibility issues.' This switch suppresses the warnings intended to help in identifying incompatibilities between Ada language versions. @@ -12491,7 +12489,7 @@ incompatibilities between Ada language versions. @item @code{-gnatw.y} -@emph{Activate information messages for why package spec needs body.} +`Activate information messages for why package spec needs body.' There are a number of cases in which a package spec needs a body. For example, the use of pragma Elaborate_Body, or the declaration @@ -12511,7 +12509,7 @@ body. The default is that such information messages are not output. @item @code{-gnatw.Y} -@emph{Disable information messages for why package spec needs body.} +`Disable information messages for why package spec needs body.' This switch suppresses the output of information messages showing why a package specification needs a body. @@ -12526,7 +12524,7 @@ a package specification needs a body. @item @code{-gnatwz} -@emph{Activate warnings on unchecked conversions.} +`Activate warnings on unchecked conversions.' This switch activates warnings for unchecked conversions where the types are known at compile time to have different @@ -12541,7 +12539,7 @@ generated for subprogram pointers with different conventions. @item @code{-gnatwZ} -@emph{Suppress warnings on unchecked conversions.} +`Suppress warnings on unchecked conversions.' This switch suppresses warnings for unchecked conversions where the types are known at compile time to have different @@ -12557,7 +12555,7 @@ sizes or conventions. @item @code{-gnatw.z} -@emph{Activate warnings for size not a multiple of alignment.} +`Activate warnings for size not a multiple of alignment.' This switch activates warnings for cases of array and record types with specified @code{Size} and @code{Alignment} attributes where the @@ -12575,7 +12573,7 @@ is that such warnings are generated. @item @code{-gnatw.Z} -@emph{Suppress warnings for size not a multiple of alignment.} +`Suppress warnings for size not a multiple of alignment.' This switch suppresses warnings for cases of array and record types with specified @code{Size} and @code{Alignment} attributes where the @@ -12615,7 +12613,7 @@ used in conjunction with an optimization level greater than zero. @table @asis -@item @code{-Wstack-usage=@emph{len}} +@item @code{-Wstack-usage=`len'} Warn if the stack usage of a subprogram might be larger than @code{len} bytes. See @ref{e6,,Static Stack Usage Analysis} for details. @@ -12956,7 +12954,7 @@ combination with optimization, since this can confuse the optimizer. If performance is a consideration, leading to the need to optimize, then the validity checking options should not be used. -The other @code{-gnatV@emph{x}} switches below allow finer-grained +The other @code{-gnatV`x'} switches below allow finer-grained control; you can enable whichever validity checks you desire. However, for most debugging purposes, @code{-gnatVa} is sufficient, and the default @code{-gnatVd} (i.e. standard Ada behavior) is usually @@ -12969,7 +12967,7 @@ the compiler can generate more efficient code, since the range of values is better known at compile time. However, an uninitialized variable can cause wild jumps and memory corruption in this mode. -The @code{-gnatV@emph{x}} switch allows control over the validity +The @code{-gnatV`x'} switch allows control over the validity checking mode as described below. The @code{x} argument is a string of letters that indicate validity checks that are performed or not performed in addition @@ -12982,7 +12980,7 @@ to the default checks required by Ada as described above. @item @code{-gnatVa} -@emph{All validity checks.} +`All validity checks.' All validity checks are turned on. That is, @code{-gnatVa} is @@ -12996,7 +12994,7 @@ equivalent to @code{gnatVcdfimoprst}. @item @code{-gnatVc} -@emph{Validity checks for copies.} +`Validity checks for copies.' The right hand side of assignments, and the initializing values of object declarations are validity checked. @@ -13009,7 +13007,7 @@ object declarations are validity checked. @item @code{-gnatVd} -@emph{Default (RM) validity checks.} +`Default (RM) validity checks.' Some validity checks are done by default following normal Ada semantics (RM 13.9.1 (9-11)). @@ -13033,7 +13031,7 @@ overwriting may occur. @item @code{-gnatVe} -@emph{Validity checks for elementary components.} +`Validity checks for elementary components.' In the absence of this switch, assignments to record or array components are not validity checked, even if validity checks for assignments generally @@ -13052,7 +13050,7 @@ are assigned component by component. @item @code{-gnatVf} -@emph{Validity checks for floating-point values.} +`Validity checks for floating-point values.' In the absence of this switch, validity checking occurs only for discrete values. If @code{-gnatVf} is specified, then validity checking also applies @@ -13072,7 +13070,7 @@ options. For example, @code{-gnatVif} or @code{-gnatVfi} @item @code{-gnatVi} -@emph{Validity checks for `@w{`}in`@w{`} mode parameters.} +`Validity checks for `@w{`}in`@w{`} mode parameters.' Arguments for parameters of mode @code{in} are validity checked in function and procedure calls at the point of call. @@ -13085,7 +13083,7 @@ and procedure calls at the point of call. @item @code{-gnatVm} -@emph{Validity checks for `@w{`}in out`@w{`} mode parameters.} +`Validity checks for `@w{`}in out`@w{`} mode parameters.' Arguments for parameters of mode @code{in out} are validity checked in procedure calls at the point of call. The @code{'m'} here stands for @@ -13103,7 +13101,7 @@ will be subject to validity checking. @item @code{-gnatVn} -@emph{No validity checks.} +`No validity checks.' This switch turns off all validity checking, including the default checking for case statements and left hand side subscripts. Note that the use of @@ -13119,7 +13117,7 @@ is used, it cancels any other @code{-gnatV} previously issued. @item @code{-gnatVo} -@emph{Validity checks for operator and attribute operands.} +`Validity checks for operator and attribute operands.' Arguments for predefined operators and attributes are validity checked. This includes all operators in package @code{Standard}, @@ -13137,7 +13135,7 @@ also made on explicit ranges using @code{..} (e.g., slices, loops etc). @item @code{-gnatVp} -@emph{Validity checks for parameters.} +`Validity checks for parameters.' This controls the treatment of parameters within a subprogram (as opposed to @code{-gnatVi} and @code{-gnatVm} which control validity testing @@ -13156,7 +13154,7 @@ will be checked (or rechecked) within the subprogram. @item @code{-gnatVr} -@emph{Validity checks for function returns.} +`Validity checks for function returns.' The expression in @code{return} statements in functions is validity checked. @@ -13169,7 +13167,7 @@ checked. @item @code{-gnatVs} -@emph{Validity checks for subscripts.} +`Validity checks for subscripts.' All subscripts expressions are checked for validity, whether they appear on the right side or left side (in default mode only left side subscripts @@ -13183,7 +13181,7 @@ are validity checked). @item @code{-gnatVt} -@emph{Validity checks for tests.} +`Validity checks for tests.' Expressions used as conditions in @code{if}, @code{while} or @code{exit} statements are checked, as well as guard expressions in entry calls. @@ -13248,7 +13246,7 @@ checks to be performed. The following checks are defined: @item @code{-gnaty0} -@emph{Specify indentation level.} +`Specify indentation level.' If a digit from 1-9 appears in the string after @code{-gnaty} @@ -13287,7 +13285,7 @@ non-blank line. @item @code{-gnatya} -@emph{Check attribute casing.} +`Check attribute casing.' Attribute names, including the case of keywords such as @code{digits} used as attributes names, must be written in mixed case, that is, the @@ -13302,7 +13300,7 @@ All other letters must be lowercase. @item @code{-gnatyA} -@emph{Use of array index numbers in array attributes.} +`Use of array index numbers in array attributes.' When using the array attributes First, Last, Range, or Length, the index number must be omitted for one-dimensional arrays @@ -13316,7 +13314,7 @@ and is required for multi-dimensional arrays. @item @code{-gnatyb} -@emph{Blanks not allowed at statement end.} +`Blanks not allowed at statement end.' Trailing blanks are not allowed at the end of statements. The purpose of this rule, together with h (no horizontal tabs), is to enforce a canonical format @@ -13330,7 +13328,7 @@ for the use of blanks to separate source tokens. @item @code{-gnatyB} -@emph{Check Boolean operators.} +`Check Boolean operators.' The use of AND/OR operators is not permitted except in the cases of modular operands, array operands, and simple stand-alone boolean variables or @@ -13345,7 +13343,7 @@ required. @item @code{-gnatyc} -@emph{Check comments, double space.} +`Check comments, double space.' Comments must meet the following set of rules: @@ -13407,7 +13405,7 @@ example: @item @code{-gnatyC} -@emph{Check comments, single space.} +`Check comments, single space.' This is identical to @code{c} except that only one space is required following the @code{--} of a comment instead of two. @@ -13420,7 +13418,7 @@ is required following the @code{--} of a comment instead of two. @item @code{-gnatyd} -@emph{Check no DOS line terminators present.} +`Check no DOS line terminators present.' All lines must be terminated by a single ASCII.LF character (in particular the DOS line terminator sequence CR/LF is not @@ -13434,7 +13432,7 @@ allowed). @item @code{-gnatyD} -@emph{Check declared identifiers in mixed case.} +`Check declared identifiers in mixed case.' Declared identifiers must be in mixed case, as in This_Is_An_Identifier. Use -gnatyr in addition to ensure @@ -13448,7 +13446,7 @@ that references match declarations. @item @code{-gnatye} -@emph{Check end/exit labels.} +`Check end/exit labels.' Optional labels on @code{end} statements ending subprograms and on @code{exit} statements exiting named loops, are required to be present. @@ -13461,7 +13459,7 @@ Optional labels on @code{end} statements ending subprograms and on @item @code{-gnatyf} -@emph{No form feeds or vertical tabs.} +`No form feeds or vertical tabs.' Neither form feeds nor vertical tab characters are permitted in the source text. @@ -13474,7 +13472,7 @@ in the source text. @item @code{-gnatyg} -@emph{GNAT style mode.} +`GNAT style mode.' The set of style check switches is set to match that used by the GNAT sources. This may be useful when developing code that is eventually intended to be @@ -13490,7 +13488,7 @@ advance notice. @item @code{-gnatyh} -@emph{No horizontal tabs.} +`No horizontal tabs.' Horizontal tab characters are not permitted in the source text. Together with the b (no blanks at end of line) check, this @@ -13505,7 +13503,7 @@ source tokens. @item @code{-gnatyi} -@emph{Check if-then layout.} +`Check if-then layout.' The keyword @code{then} must appear either on the same line as corresponding @code{if}, or on a line on its own, lined @@ -13519,7 +13517,7 @@ up under the @code{if}. @item @code{-gnatyI} -@emph{check mode IN keywords.} +`check mode IN keywords.' Mode @code{in} (the default mode) is not allowed to be given explicitly. @code{in out} is fine, @@ -13533,7 +13531,7 @@ but not @code{in} on its own. @item @code{-gnatyk} -@emph{Check keyword casing.} +`Check keyword casing.' All keywords must be in lower case (with the exception of keywords such as @code{digits} used as attribute names to which this check @@ -13548,7 +13546,7 @@ this rule even if multiple casing issues exist on a same line. @item @code{-gnatyl} -@emph{Check layout.} +`Check layout.' Layout of statement and declaration constructs must follow the recommendations in the Ada Reference Manual, as indicated by the @@ -13624,11 +13622,11 @@ Clear : @item @code{-gnatyL} -@emph{Set maximum nesting level.} +`Set maximum nesting level.' The maximum level of nesting of constructs (including subprograms, loops, blocks, packages, and conditionals) may not exceed the given value -@emph{nnn}. A value of zero disconnects this style check. +`nnn'. A value of zero disconnects this style check. @end table @geindex -gnatym (gcc) @@ -13638,7 +13636,7 @@ blocks, packages, and conditionals) may not exceed the given value @item @code{-gnatym} -@emph{Check maximum line length.} +`Check maximum line length.' The length of source lines must not exceed 79 characters, including any trailing blanks. The value of 79 allows convenient display on an @@ -13656,10 +13654,10 @@ a single character (however many bytes are needed in the encoding). @item @code{-gnatyM} -@emph{Set maximum line length.} +`Set maximum line length.' The length of lines must not exceed the -given value @emph{nnn}. The maximum value that can be specified is 32767. +given value `nnn'. The maximum value that can be specified is 32767. If neither style option for setting the line length is used, then the default is 255. This also controls the maximum length of lexical elements, where the only restriction is that they must fit on a single line. @@ -13672,7 +13670,7 @@ where the only restriction is that they must fit on a single line. @item @code{-gnatyn} -@emph{Check casing of entities in Standard.} +`Check casing of entities in Standard.' Any identifier from Standard must be cased to match the presentation in the Ada Reference Manual (for example, @@ -13686,7 +13684,7 @@ to match the presentation in the Ada Reference Manual (for example, @item @code{-gnatyN} -@emph{Turn off all style checks.} +`Turn off all style checks.' All style check options are turned off. @end table @@ -13698,7 +13696,7 @@ All style check options are turned off. @item @code{-gnatyo} -@emph{Check order of subprogram bodies.} +`Check order of subprogram bodies.' All subprogram bodies in a given scope (e.g., a package body) must be in alphabetical order. The ordering @@ -13715,7 +13713,7 @@ before Junk10). @item @code{-gnatyO} -@emph{Check that overriding subprograms are explicitly marked as such.} +`Check that overriding subprograms are explicitly marked as such.' This applies to all subprograms of a derived type that override a primitive operation of the type, for both tagged and untagged types. In particular, @@ -13732,7 +13730,7 @@ as an equality operator). @item @code{-gnatyp} -@emph{Check pragma casing.} +`Check pragma casing.' Pragma names must be written in mixed case, that is, the initial letter and any letter following an underscore must be uppercase. @@ -13747,7 +13745,7 @@ allowed as an alternative for Spark_Mode. @item @code{-gnatyr} -@emph{Check references.} +`Check references.' All identifier references must be cased in the same way as the corresponding declaration. No specific casing style is imposed on @@ -13762,7 +13760,7 @@ with declarations. @item @code{-gnatys} -@emph{Check separate specs.} +`Check separate specs.' Separate declarations (‘specs’) are required for subprograms (a body is not allowed to serve as its own declaration). The only @@ -13778,7 +13776,7 @@ the most frequent form of main program procedures. @item @code{-gnatyS} -@emph{Check no statements after then/else.} +`Check no statements after then/else.' No statements are allowed on the same line as a @code{then} or @code{else} keyword following the @@ -13793,7 +13791,7 @@ affected, and a special exception allows a pragma to appear after @code{else}. @item @code{-gnatyt} -@emph{Check token spacing.} +`Check token spacing.' The following token spacing rules are enforced: @@ -13858,7 +13856,7 @@ a @code{not} token and a following @code{in} token. @item @code{-gnatyu} -@emph{Check unnecessary blank lines.} +`Check unnecessary blank lines.' Unnecessary blank lines are not allowed. A blank line is considered unnecessary if it appears at the end of the file, or if more than @@ -13872,7 +13870,7 @@ one blank line occurs in sequence. @item @code{-gnatyx} -@emph{Check extra parentheses.} +`Check extra parentheses.' Unnecessary extra level of parentheses (C-style) are not allowed around conditions in @code{if} statements, @code{while} statements and @@ -13886,7 +13884,7 @@ around conditions in @code{if} statements, @code{while} statements and @item @code{-gnatyy} -@emph{Set all standard style check options.} +`Set all standard style check options.' This is equivalent to @code{gnaty3aAbcefhiklmnprst}, that is all checking options enabled with the exception of @code{-gnatyB}, @code{-gnatyd}, @@ -13901,15 +13899,15 @@ options enabled with the exception of @code{-gnatyB}, @code{-gnatyd}, @item @code{-gnaty-} -@emph{Remove style check options.} +`Remove style check options.' This causes any subsequent options in the string to act as canceling the corresponding style check option. To cancel maximum nesting level control, use the @code{L} parameter without any integer value after that, because any -digit following @emph{-} in the parameter string of the @code{-gnaty} +digit following `-' in the parameter string of the @code{-gnaty} option will be treated as canceling the indentation check. The same is true for the @code{M} parameter. @code{y} and @code{N} parameters are not -allowed after @emph{-}. +allowed after `-'. @end table @geindex -gnaty+ (gcc) @@ -13919,7 +13917,7 @@ allowed after @emph{-}. @item @code{-gnaty+} -@emph{Enable style check options.} +`Enable style check options.' This causes any subsequent options in the string to enable the corresponding style check option. That is, it cancels the effect of a previous -, @@ -14076,20 +14074,20 @@ controls the mode, using the codes @table @asis -@item @emph{1 = STRICT} +@item `1 = STRICT' In STRICT mode, intermediate operations are always done using the base type, and overflow checking ensures that the result is within the base type range. -@item @emph{2 = MINIMIZED} +@item `2 = MINIMIZED' In MINIMIZED mode, overflows in intermediate operations are avoided where possible by using a larger integer type for the computation (typically @code{Long_Long_Integer}). Overflow checking ensures that the result fits in this larger integer type. -@item @emph{3 = ELIMINATED} +@item `3 = ELIMINATED' In ELIMINATED mode, overflows in intermediate operations are avoided by using multi-precision arithmetic. In this case, overflow checking @@ -14216,7 +14214,7 @@ $ Otherwise, the output is simply the error messages, if any. No object file or ALI file is generated by a syntax-only compilation. Also, no units other than the one specified are accessed. For example, if a unit @code{X} -@emph{with}s a unit @code{Y}, compiling unit @code{X} in syntax +`with's a unit @code{Y}, compiling unit @code{X} in syntax check only mode does not access the source file containing unit @code{Y}. @@ -14325,7 +14323,7 @@ with optional bodies), it is not necessary to specify the exceptions, Ada 95 and Ada 2005 are upwardly compatible with Ada 83. Thus a correct Ada 83 program is usually also a correct program in these later versions of the language standard. For further information -please refer to the @emph{Compatibility and Porting Guide} chapter in the +please refer to the `Compatibility and Porting Guide' chapter in the @cite{GNAT Reference Manual}. @end table @@ -14434,7 +14432,7 @@ extensions, see the GNAT reference manual, @code{Pragma Extensions_Allowed}. @table @asis -@item @code{-gnati@emph{c}} +@item @code{-gnati`c'} Normally GNAT recognizes the Latin-1 character set in source program identifiers, as described in the Ada Reference Manual. @@ -14446,7 +14444,7 @@ single character indicating the character set, as follows: @multitable {xxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @item -@emph{1} +`1' @tab @@ -14454,7 +14452,7 @@ ISO 8859-1 (Latin-1) identifiers @item -@emph{2} +`2' @tab @@ -14462,7 +14460,7 @@ ISO 8859-2 (Latin-2) letters allowed in identifiers @item -@emph{3} +`3' @tab @@ -14470,7 +14468,7 @@ ISO 8859-3 (Latin-3) letters allowed in identifiers @item -@emph{4} +`4' @tab @@ -14478,7 +14476,7 @@ ISO 8859-4 (Latin-4) letters allowed in identifiers @item -@emph{5} +`5' @tab @@ -14486,7 +14484,7 @@ ISO 8859-5 (Cyrillic) letters allowed in identifiers @item -@emph{9} +`9' @tab @@ -14494,7 +14492,7 @@ ISO 8859-15 (Latin-9) letters allowed in identifiers @item -@emph{p} +`p' @tab @@ -14502,7 +14500,7 @@ IBM PC letters (code page 437) allowed in identifiers @item -@emph{8} +`8' @tab @@ -14510,7 +14508,7 @@ IBM PC letters (code page 850) allowed in identifiers @item -@emph{f} +`f' @tab @@ -14518,7 +14516,7 @@ Full upper-half codes allowed in identifiers @item -@emph{n} +`n' @tab @@ -14526,7 +14524,7 @@ No upper-half codes allowed in identifiers @item -@emph{w} +`w' @tab @@ -14545,7 +14543,7 @@ implementation of these character sets. @table @asis -@item @code{-gnatW@emph{e}} +@item @code{-gnatW`e'} Specify the method of encoding for wide characters. @code{e} is one of the following: @@ -14554,7 +14552,7 @@ Specify the method of encoding for wide characters. @multitable {xxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @item -@emph{h} +`h' @tab @@ -14562,7 +14560,7 @@ Hex encoding (brackets coding also recognized) @item -@emph{u} +`u' @tab @@ -14570,7 +14568,7 @@ Upper half encoding (brackets encoding also recognized) @item -@emph{s} +`s' @tab @@ -14578,7 +14576,7 @@ Shift/JIS encoding (brackets encoding also recognized) @item -@emph{e} +`e' @tab @@ -14586,7 +14584,7 @@ EUC encoding (brackets encoding also recognized) @item -@emph{8} +`8' @tab @@ -14594,7 +14592,7 @@ UTF-8 encoding (brackets encoding also recognized) @item -@emph{b} +`b' @tab @@ -14661,7 +14659,7 @@ This is a common mode for many programs with foreign language comments. @table @asis -@item @code{-gnatk@emph{n}} +@item @code{-gnatk`n'} Activates file name ‘krunching’. @code{n}, a decimal integer in the range 1-999, indicates the maximum allowable length of a file name (not @@ -14760,7 +14758,7 @@ react to a compilation failure. Those exit status are: @multitable {xxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @item -@emph{5} +`5' @tab @@ -14768,7 +14766,7 @@ There was an error in at least one source file. @item -@emph{3} +`3' @tab @@ -14776,7 +14774,7 @@ At least one source file did not generate an object file. @item -@emph{2} +`2' @tab @@ -14784,7 +14782,7 @@ The compiler died unexpectedly (internal error for example). @item -@emph{0} +`0' @tab @@ -14809,7 +14807,7 @@ An object file has been generated for every source file. @table @asis -@item @code{-gnatd@emph{x}} +@item @code{-gnatd`x'} Activate internal debugging switches. @code{x} is a letter or digit, or string of letters or digits, which specifies the type of debugging @@ -14824,7 +14822,7 @@ file @code{debug.adb}. @table @asis -@item @code{-gnatG[=@emph{nn}]} +@item @code{-gnatG[=`nn']} This switch causes the compiler to generate auxiliary output containing a pseudo-source listing of the generated expanded code. Like most Ada @@ -14860,47 +14858,47 @@ in the expanded source (as comment lines with the original line number). @table @asis -@item @code{new @emph{xxx} [storage_pool = @emph{yyy}]} +@item @code{new @var{xxx} [storage_pool = @var{yyy}]} Shows the storage pool being used for an allocator. -@item @code{at end @emph{procedure-name};} +@item @code{at end @var{procedure-name};} Shows the finalization (cleanup) procedure for a scope. -@item @code{(if @emph{expr} then @emph{expr} else @emph{expr})} +@item @code{(if @var{expr} then @var{expr} else @var{expr})} Conditional expression equivalent to the @code{x?y:z} construction in C. -@item @code{@emph{target}^(@emph{source})} +@item @code{@var{target}^(@var{source})} A conversion with floating-point truncation instead of rounding. -@item @code{@emph{target}?(@emph{source})} +@item @code{@var{target}?(@var{source})} A conversion that bypasses normal Ada semantic checking. In particular enumeration types and fixed-point types are treated simply as integers. -@item @code{@emph{target}?^(@emph{source})} +@item @code{@var{target}?^(@var{source})} Combines the above two cases. @end table -@code{@emph{x} #/ @emph{y}} +@code{@var{x} #/ @var{y}} -@code{@emph{x} #mod @emph{y}} +@code{@var{x} #mod @var{y}} -@code{@emph{x} # @emph{y}} +@code{@var{x} # @var{y}} @table @asis -@item @code{@emph{x} #rem @emph{y}} +@item @code{@var{x} #rem @var{y}} A division or multiplication of fixed-point values which are treated as integers without any kind of scaling. -@item @code{free @emph{expr} [storage_pool = @emph{xxx}]} +@item @code{free @var{expr} [storage_pool = @var{xxx}]} Shows the storage pool associated with a @code{free} statement. @@ -14909,30 +14907,30 @@ Shows the storage pool associated with a @code{free} statement. Used to list an equivalent declaration for an internally generated type that is referenced elsewhere in the listing. -@item @code{freeze @emph{type-name} [@emph{actions}]} +@item @code{freeze @var{type-name} [@var{actions}]} Shows the point at which @code{type-name} is frozen, with possible associated actions to be performed at the freeze point. -@item @code{reference @emph{itype}} +@item @code{reference @var{itype}} Reference (and hence definition) to internal type @code{itype}. -@item @code{@emph{function-name}! (@emph{arg}, @emph{arg}, @emph{arg})} +@item @code{@var{function-name}! (@var{arg}, @var{arg}, @var{arg})} Intrinsic function call. -@item @code{@emph{label-name} : label} +@item @code{@var{label-name} : label} Declaration of label @code{labelname}. -@item @code{#$ @emph{subprogram-name}} +@item @code{#$ @var{subprogram-name}} An implicit call to a run-time support routine (to meet the requirement of H.3.1(9) in a convenient manner). -@item @code{@emph{expr} && @emph{expr} && @emph{expr} ... && @emph{expr}} +@item @code{@var{expr} && @var{expr} && @var{expr} ... && @var{expr}} A multiple concatenation (same effect as @code{expr} & @code{expr} & @code{expr}, but handled more efficiently). @@ -14941,15 +14939,15 @@ A multiple concatenation (same effect as @code{expr} & @code{expr} & Raise the @code{Constraint_Error} exception. -@item @code{@emph{expression}'reference} +@item @code{@var{expression}'reference} A pointer to the result of evaluating @{expression@}. -@item @code{@emph{target-type}!(@emph{source-expression})} +@item @code{@var{target-type}!(@var{source-expression})} An unchecked conversion of @code{source-expression} to @code{target-type}. -@item @code{[@emph{numerator}/@emph{denominator}]} +@item @code{[@var{numerator}/@var{denominator}]} Used to represent internal real literals (that) have no exact representation in base 2-16 (for example, the result of compile time @@ -15225,7 +15223,7 @@ through the compilation and binding steps. @table @asis -@item @code{-gnatem=@emph{path}} +@item @code{-gnatem=`path'} A mapping file is a way to communicate to the compiler two mappings: from unit names to file names (without any directory information) and from @@ -15308,7 +15306,7 @@ Linker switches can be specified after @code{-largs} builder switch. @table @asis -@item @code{-fuse-ld=@emph{name}} +@item @code{-fuse-ld=`name'} Linker to be used. The default is @code{bfd} for @code{ld.bfd}, the alternative being @code{gold} for @code{ld.gold}. The later is @@ -15519,7 +15517,7 @@ Specify directory to be searched for source file. @table @asis -@item @code{-A[=@emph{filename}]} +@item @code{-A[=`filename']} Output ALI list (to standard output or to the named file). @end table @@ -15549,7 +15547,7 @@ Check only, no generation of binder output file. @table @asis -@item @code{-d@emph{nn}[k|m]} +@item @code{-d`nn'[k|m]} This switch can be used to change the default task stack size value to a specified size @code{nn}, which is expressed in bytes by default, or @@ -15570,7 +15568,7 @@ When they do not already have such a pragma. @table @asis -@item @code{-D@emph{nn}[k|m]} +@item @code{-D`nn'[k|m]} Set the default secondary stack size to @code{nn}. The suffix indicates whether the size is in bytes (no suffix), kilobytes (@code{k} suffix) or megabytes @@ -15646,7 +15644,7 @@ Currently the same as @code{-Ea}. @table @asis -@item @code{-f@emph{elab-order}} +@item @code{-f`elab-order'} Force elaboration order. For further details see @ref{111,,Elaboration Control} and @ref{f,,Elaboration Order Handling in GNAT}. @@ -15726,6 +15724,22 @@ Do not look for sources in the current directory where @code{gnatbind} was invoked, and do not look for ALI files in the directory containing the ALI file named in the @code{gnatbind} command line. +@geindex -k (gnatbind) + +@item @code{-k} + +Disable checking of elaboration flags. When using @code{-n} +either explicitly or implicitly, @code{-F} is also implied, +unless @code{-k} is used. This switch should be used with care +and you should ensure manually that elaboration routines are not called +twice unintentionally. + +@geindex -K (gnatbind) + +@item @code{-K} + +Give list of linker options specified for link. + @geindex -l (gnatbind) @item @code{-l} @@ -15734,25 +15748,25 @@ Output chosen elaboration order. @geindex -L (gnatbind) -@item @code{-L@emph{xxx}} +@item @code{-L`xxx'} Bind the units for library building. In this case the @code{adainit} and @code{adafinal} procedures (@ref{a0,,Binding with Non-Ada Main Programs}) -are renamed to @code{@emph{xxx}init} and -@code{@emph{xxx}final}. +are renamed to @code{@var{xxx}init} and +@code{@var{xxx}final}. Implies -n. (@ref{2a,,GNAT and Libraries}, for more details.) @geindex -M (gnatbind) -@item @code{-M@emph{xyz}} +@item @code{-M`xyz'} Rename generated main program from main to xyz. This option is supported on cross environments only. @geindex -m (gnatbind) -@item @code{-m@emph{n}} +@item @code{-m`n'} Limit number of detected errors or warnings to @code{n}, where @code{n} is in the range 1..999999. The default value if no switch is @@ -15769,7 +15783,7 @@ sign is optional. Generate a binder file suitable for space-constrained applications. When active, binder-generated objects not required for program operation are no -longer generated. @strong{Warning:} this option comes with the following +longer generated. `Warning:' this option comes with the following limitations: @@ -15805,14 +15819,14 @@ Do not look for library files in the system default directory. @geindex --RTS (gnatbind) -@item @code{--RTS=@emph{rts-path}} +@item @code{--RTS=`rts-path'} Specifies the default location of the run-time library. Same meaning as the equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @geindex -o (gnatbind) -@item @code{-o @emph{file}} +@item @code{-o `file'} Name the output file @code{file} (default is @code{b~`xxx}.adb`). Note that if this option is used, then linking must be done manually, @@ -15820,7 +15834,7 @@ gnatlink cannot be used. @geindex -O (gnatbind) -@item @code{-O[=@emph{filename}]} +@item @code{-O[=`filename']} Output object list (to standard output or to the named file). @@ -15857,7 +15871,7 @@ Require all source files to be present. @geindex -S (gnatbind) -@item @code{-S@emph{xxx}} +@item @code{-S`xxx'} Specifies the value to be used when detecting uninitialized scalar objects with pragma Initialize_Scalars. @@ -15911,8 +15925,8 @@ then a 32-bit scalar value will be set to the bit patterm @code{16#BFBFBFBF#}. In addition, you can specify @code{-Sev} to indicate that the value is to be set at run time. In this case, the program will look for an environment -variable of the form @code{GNAT_INIT_SCALARS=@emph{yy}}, where @code{yy} is one -of @code{in/lo/hi/@emph{xx}} with the same meanings as above. +variable of the form @code{GNAT_INIT_SCALARS=@var{yy}}, where @code{yy} is one +of @code{in/lo/hi/@var{xx}} with the same meanings as above. If no environment variable is found, or if it does not have a valid value, then the default is @code{in} (invalid values). @end table @@ -15940,7 +15954,7 @@ Tolerate time stamp and other consistency errors. @geindex -T (gnatbind) -@item @code{-T@emph{n}} +@item @code{-T`n'} Set the time slice value to @code{n} milliseconds. If the system supports the specification of a specific time slice value, then the indicated value @@ -15956,7 +15970,7 @@ scheduling policy to @code{FIFO_Within_Priorities}. @geindex -u (gnatbind) -@item @code{-u@emph{n}} +@item @code{-u`n'} Enable dynamic stack usage, with @code{n} results stored and displayed at program termination. A result is generated when a task @@ -15973,7 +15987,7 @@ Verbose mode. Write error messages, header, summary output to @geindex -V (gnatbind) -@item @code{-V@emph{key}=@emph{value}} +@item @code{-V`key'=`value'} Store the given association of @code{key} to @code{value} in the bind environment. Values stored this way can be retrieved at run time using @@ -15981,13 +15995,13 @@ Values stored this way can be retrieved at run time using @geindex -w (gnatbind) -@item @code{-w@emph{x}} +@item @code{-w`x'} Warning mode; @code{x} = s/e for suppress/treat as error. @geindex -Wx (gnatbind) -@item @code{-Wx@emph{e}} +@item @code{-Wx`e'} Override default wide character encoding for standard Text_IO files. @@ -16010,7 +16024,7 @@ at streaming 128-bit integer types with it. @geindex -Xnnn (gnatbind) -@item @code{-X@emph{nnn}} +@item @code{-X`nnn'} Set default exit status value, normally 0 for POSIX compliance. @@ -16069,7 +16083,7 @@ file is an error. @geindex -Wx (gnatbind) -@item @code{-Wx@emph{e}} +@item @code{-Wx`e'} Override default wide character encoding for standard Text_IO files. Normally the default wide character encoding method used for standard @@ -16128,14 +16142,14 @@ specified. This is relevant only when used with the @geindex -m (gnatbind) -@item @code{-m@emph{n}} +@item @code{-m`n'} Limits the number of error messages to @code{n}, a decimal integer in the range 1-999. The binder terminates immediately if this limit is reached. @geindex -M (gnatbind) -@item @code{-M@emph{xxx}} +@item @code{-M`xxx'} Renames the generated main program from @code{main} to @code{xxx}. This is useful in the case of some cross-building environments, where @@ -16218,7 +16232,7 @@ order. For further details see @ref{f,,Elaboration Order Handling in GNAT}. @table @asis -@item @code{-f@emph{elab-order}} +@item @code{-f`elab-order'} Force elaboration order. @@ -16353,7 +16367,7 @@ directory names for the run-time units depend on the system configuration. @geindex -o (gnatbind) -@item @code{-o @emph{file}} +@item @code{-o `file'} Set name of output file to @code{file} instead of the normal @code{b~`mainprog}.adb` default. Note that @code{file} denote the Ada @@ -16473,7 +16487,7 @@ is given, more than one ALI file may appear on the command line for @code{gnatbind}. The normal @code{closure} calculation is performed for each of the specified units. Calculating the closure means finding out the set of units involved by tracing -@emph{with} references. The reason it is necessary to be able to +`with' references. The reason it is necessary to be able to specify more than one ALI file is that a given program may invoke two or more quite separate groups of Ada units. @@ -16544,9 +16558,9 @@ char **gnat_argv; are declared in one of the GNAT library routines. These variables must be set from the actual @code{argc} and @code{argv} values passed to the -main program. With no @emph{n} present, @code{gnatbind} +main program. With no `n' present, @code{gnatbind} generates the C main program to automatically set these variables. -If the @emph{n} switch is used, there is no automatic way to +If the `n' switch is used, there is no automatic way to set these variables. If they are not set, the procedures in @code{Ada.Command_Line} will not be available, and any attempt to use them will raise @code{Constraint_Error}. If command line access is @@ -16628,9 +16642,9 @@ instead if you want to specify source paths only, and @code{-aO} if you want to specify library paths only. This means that for the binder -@code{-I@emph{dir}} is equivalent to -@code{-aI@emph{dir}} -@code{-aO`@emph{dir}}. +@code{-I`dir'} is equivalent to +@code{-aI`dir'} +@code{-aO``dir'}. The binder generates the bind file (a C language source file) in the current working directory. @@ -16881,7 +16895,7 @@ it compiles the binder file, and that the system linker run in verbose mode. @table @asis -@item @code{-o @emph{exec-name}} +@item @code{-o `exec-name'} @code{exec-name} specifies an alternate name for the generated executable program. If this switch is omitted, the executable has the same @@ -16894,7 +16908,7 @@ an executable called @code{try}. @table @asis -@item @code{-B@emph{dir}} +@item @code{-B`dir'} Load compiler executables (for example, @code{gnat1}, the Ada compiler) from @code{dir} instead of the default location. Only use this switch @@ -16920,7 +16934,7 @@ has the same name as the executable with extension “.mapâ€. @table @asis -@item @code{-M=@emph{mapfile}} +@item @code{-M=`mapfile'} When linking an executable, create a map file. The name of the map file is @code{mapfile}. @@ -16931,7 +16945,7 @@ When linking an executable, create a map file. The name of the map file is @table @asis -@item @code{--GCC=@emph{compiler_name}} +@item @code{--GCC=`compiler_name'} Program used for compiling the binder file. The default is @code{gcc}. You need to use quotes around @code{compiler_name} if @@ -16958,7 +16972,7 @@ into account. Thus, @table @asis -@item @code{--LINK=@emph{name}} +@item @code{--LINK=`name'} @code{name} is the name of the linker to be invoked. This is especially useful in mixed language programs since languages such as C++ require @@ -17366,7 +17380,7 @@ Display copyright and version, then exit disregarding all other options. If @code{--version} was not used, display usage, then exit disregarding all other options. -@item @code{--subdirs=@emph{subdir}} +@item @code{--subdirs=`subdir'} Actual object directory of each project file is the subdirectory subdir of the object directory specified or defaulted in the project file. @@ -17395,7 +17409,7 @@ files, interface copy files, binder generated files and executable files. @table @asis -@item @code{-D @emph{dir}} +@item @code{-D `dir'} Indicate that ALI and object files should normally be found in directory @code{dir}. @end table @@ -17439,7 +17453,7 @@ that would have been deleted if this switch was not specified. @table @asis -@item @code{-P@emph{project}} +@item @code{-P`project'} Use project file @code{project}. Only one such switch can be used. When cleaning a project file, the files produced by the compilation of the @@ -17488,7 +17502,7 @@ Verbose mode. @table @asis -@item @code{-vP@emph{x}} +@item @code{-vP`x'} Indicates the verbosity of the parsing of GNAT project files. @ref{cf,,Switches Related to Project Files}. @@ -17499,7 +17513,7 @@ Indicates the verbosity of the parsing of GNAT project files. @table @asis -@item @code{-X@emph{name}=@emph{value}} +@item @code{-X`name'=`value'} Indicates that external variable @code{name} has the value @code{value}. The Project Manager will use this value for occurrences of @@ -17512,7 +17526,7 @@ See @ref{cf,,Switches Related to Project Files}. @table @asis -@item @code{-aO@emph{dir}} +@item @code{-aO`dir'} When searching for ALI and object files, look in directory @code{dir}. @end table @@ -17522,9 +17536,9 @@ When searching for ALI and object files, look in directory @code{dir}. @table @asis -@item @code{-I@emph{dir}} +@item @code{-I`dir'} -Equivalent to @code{-aO@emph{dir}}. +Equivalent to @code{-aO`dir'}. @end table @geindex -I- (gnatclean) @@ -17613,12 +17627,12 @@ qualifier which can be: @table @asis -@item @emph{OK (unchanged)} +@item `OK (unchanged)' The version of the source file used for the compilation of the specified unit corresponds exactly to the actual source file. -@item @emph{MOK (slightly modified)} +@item `MOK (slightly modified)' The version of the source file used for the compilation of the specified unit differs from the actual source file but not enough to @@ -17626,16 +17640,16 @@ require recompilation. If you use gnatmake with the option @code{-m} (minimal recompilation), a file marked MOK will not be recompiled. -@item @emph{DIF (modified)} +@item `DIF (modified)' No version of the source found on the path corresponds to the source used to build this object. -@item @emph{??? (file not found)} +@item `??? (file not found)' No source file was found for this unit. -@item @emph{HID (hidden, unchanged version not first on PATH)} +@item `HID (hidden, unchanged version not first on PATH)' The version of the source that corresponds exactly to the source used for compilation has been found on the path but it is hidden by another @@ -17736,7 +17750,7 @@ Only output information about compilation units. @table @asis -@item @code{-files=@emph{file}} +@item @code{-files=`file'} Take as arguments the files listed in text file @code{file}. Text file @code{file} may contain empty lines that are ignored. @@ -17755,7 +17769,7 @@ Several such switches may be specified simultaneously. @table @asis -@item @code{-aO@emph{dir}}, @code{-aI@emph{dir}}, @code{-I@emph{dir}}, @code{-I-}, @code{-nostdinc} +@item @code{-aO`dir'}, @code{-aI`dir'}, @code{-I`dir'}, @code{-I-}, @code{-nostdinc} Source path manipulation. Same meaning as the equivalent @code{gnatmake} flags (@ref{ce,,Switches for gnatmake}). @@ -17766,7 +17780,7 @@ flags (@ref{ce,,Switches for gnatmake}). @table @asis -@item @code{-aP@emph{dir}} +@item @code{-aP`dir'} Add @code{dir} at the beginning of the project search dir. @end table @@ -17776,7 +17790,7 @@ Add @code{dir} at the beginning of the project search dir. @table @asis -@item @code{--RTS=@emph{rts-path}} +@item @code{--RTS=`rts-path'} Specifies the default location of the runtime library. Same meaning as the equivalent @code{gnatmake} flag (@ref{ce,,Switches for gnatmake}). @@ -17798,29 +17812,29 @@ characteristics such as: @itemize * @item -@emph{Preelaborable}: The unit is preelaborable in the Ada sense. +`Preelaborable': The unit is preelaborable in the Ada sense. @item -@emph{No_Elab_Code}: No elaboration code has been produced by the compiler for this unit. +`No_Elab_Code': No elaboration code has been produced by the compiler for this unit. @item -@emph{Pure}: The unit is pure in the Ada sense. +`Pure': The unit is pure in the Ada sense. @item -@emph{Elaborate_Body}: The unit contains a pragma Elaborate_Body. +`Elaborate_Body': The unit contains a pragma Elaborate_Body. @item -@emph{Remote_Types}: The unit contains a pragma Remote_Types. +`Remote_Types': The unit contains a pragma Remote_Types. @item -@emph{Shared_Passive}: The unit contains a pragma Shared_Passive. +`Shared_Passive': The unit contains a pragma Shared_Passive. @item -@emph{Predefined}: This unit is part of the predefined environment and cannot be modified +`Predefined': This unit is part of the predefined environment and cannot be modified by the user. @item -@emph{Remote_Call_Interface}: The unit contains a pragma Remote_Call_Interface. +`Remote_Call_Interface': The unit contains a pragma Remote_Call_Interface. @end itemize @end table @@ -18101,7 +18115,7 @@ describes some of the additional commands that can be given to @code{GDB}. @code{GDB} contains a large repertoire of commands. See @cite{Debugging with GDB} for extensive documentation on the use of these commands, together with examples of their use. Furthermore, -the command @emph{help} invoked from within GDB activates a simple help +the command `help' invoked from within GDB activates a simple help facility which summarizes the available commands and their options. In this section we summarize a few of the most commonly used commands to give an idea of what @code{GDB} is about. You should create @@ -18116,9 +18130,9 @@ following section. @table @asis -@item @code{set args @emph{arguments}} +@item @code{set args @var{arguments}} -The @emph{arguments} list above is a list of arguments to be passed to +The `arguments' list above is a list of arguments to be passed to the program on a subsequent run command, just as though the arguments had been entered on a normal invocation of the program. The @code{set args} command is not needed if the program does not require arguments. @@ -18141,11 +18155,11 @@ restart. @table @asis -@item @code{breakpoint @emph{location}} +@item @code{breakpoint @var{location}} The breakpoint command sets a breakpoint, that is to say a point at which execution will halt and @code{GDB} will await further -commands. @emph{location} is +commands. `location' is either a line number within a file, given in the format @code{file:linenumber}, or it is the name of a subprogram. If you request that a breakpoint be set on a subprogram that is overloaded, a prompt will ask you to specify on which of @@ -18160,7 +18174,7 @@ printing the line of code before which the program is halted. @table @asis -@item @code{catch exception @emph{name}} +@item @code{catch exception @var{name}} This command causes the program execution to stop whenever exception @code{name} is raised. If @code{name} is omitted, then the execution is @@ -18171,7 +18185,7 @@ suspended when any exception is raised. @table @asis -@item @code{print @emph{expression}} +@item @code{print @var{expression}} This will print the value of the given expression. Most simple Ada expression formats are properly handled by @code{GDB}, so the expression @@ -18260,7 +18274,7 @@ examined to the frame of its callee (the reverse of the previous command), @table @asis -@item @code{frame @emph{n}} +@item @code{frame @var{n}} Inspect the frame with the given number. The value 0 denotes the frame of the current breakpoint, that is to say the top of the call stack. @@ -18400,7 +18414,7 @@ the elements in the desired format. @node Using the next Command in a Function,Stopping When Ada Exceptions Are Raised,Calling User-Defined Subprograms,Running and Debugging Ada Programs @anchor{gnat_ugn/gnat_and_program_execution id8}@anchor{158}@anchor{gnat_ugn/gnat_and_program_execution using-the-next-command-in-a-function}@anchor{159} -@subsection Using the @emph{next} Command in a Function +@subsection Using the `next' Command in a Function When you use the @code{next} command in a function, the current source @@ -18448,10 +18462,10 @@ raises any exception. @table @asis -@item @code{catch exception @emph{name}} +@item @code{catch exception @var{name}} Set a catchpoint that stops execution whenever (any task in the) program -raises the exception @emph{name}. +raises the exception `name'. @end table @item @@ -18468,11 +18482,11 @@ raises an exception for which there is no handler. @table @asis -@item @code{info exceptions}, @code{info exceptions @emph{regexp}} +@item @code{info exceptions}, @code{info exceptions @var{regexp}} The @code{info exceptions} command permits the user to examine all defined -exceptions within Ada programs. With a regular expression, @emph{regexp}, as -argument, prints out only those exceptions whose name matches @emph{regexp}. +exceptions within Ada programs. With a regular expression, `regexp', as +argument, prints out only those exceptions whose name matches `regexp'. @end table @end itemize @@ -18517,25 +18531,25 @@ to refer to tasks in the following commands. @itemize * @item -@code{break} @emph{linespec} @code{task} @emph{taskid}, @code{break} @emph{linespec} @code{task} @emph{taskid} @code{if} … +@code{break} `linespec' @code{task} `taskid', @code{break} `linespec' @code{task} `taskid' @code{if} … @quotation These commands are like the @code{break ... thread ...}. -@emph{linespec} specifies source lines. +`linespec' specifies source lines. -Use the qualifier @code{task @emph{taskid}} with a breakpoint command +Use the qualifier @code{task @var{taskid}} with a breakpoint command to specify that you only want @code{GDB} to stop the program when a -particular Ada task reaches this breakpoint. @emph{taskid} is one of the +particular Ada task reaches this breakpoint. `taskid' is one of the numeric task identifiers assigned by @code{GDB}, shown in the first column of the @code{info tasks} display. -If you do not specify @code{task @emph{taskid}} when you set a -breakpoint, the breakpoint applies to @emph{all} tasks of your +If you do not specify @code{task @var{taskid}} when you set a +breakpoint, the breakpoint applies to `all' tasks of your program. You can use the @code{task} qualifier on conditional breakpoints as -well; in this case, place @code{task @emph{taskid}} before the +well; in this case, place @code{task @var{taskid}} before the breakpoint condition (before the @code{if}). @end quotation @end itemize @@ -18546,11 +18560,11 @@ breakpoint condition (before the @code{if}). @itemize * @item -@code{task @emph{taskno}} +@code{task @var{taskno}} @quotation -This command allows switching to the task referred by @emph{taskno}. In +This command allows switching to the task referred by `taskno'. In particular, this allows browsing of the backtrace of the specified task. It is advisable to switch back to the original task before continuing execution otherwise the scheduling of the program may be @@ -18676,7 +18690,7 @@ It is also possible to use gdbserver to attach to an already running program, in which case the execution of that program is simply suspended until the connection between the debugger and gdbserver is established. -For more information on how to use gdbserver, see the @emph{Using the gdbserver Program} +For more information on how to use gdbserver, see the `Using the gdbserver Program' section in @cite{Debugging with GDB}. GNAT provides support for gdbserver on x86-linux, x86-windows and x86_64-linux. @@ -18863,7 +18877,7 @@ are replaced with run-time calls. Traceback is a mechanism to display the sequence of subprogram calls that leads to a specified execution point in a program. Often (but not always) the execution point is an instruction at which an exception has been raised. -This mechanism is also known as @emph{stack unwinding} because it obtains +This mechanism is also known as `stack unwinding' because it obtains its information by scanning the run-time stack and recovering the activation records of all active subprograms. Stack unwinding is one of the most important tools for program debugging. @@ -18897,12 +18911,14 @@ for a complete list of supported platforms. A runtime non-symbolic traceback is a list of addresses of call instructions. -To enable this feature you must use the @code{-E} -@code{gnatbind} option. With this option a stack traceback is stored as part -of exception information. You can retrieve this information using the -@code{addr2line} tool. +To enable this feature you must use the @code{-E} @code{gnatbind} option. With +this option a stack traceback is stored as part of exception information. -Here is a simple example: +You can translate this information using the @code{addr2line} tool, provided that +the program is compiled with debugging options (see @ref{db,,Compiler Switches}) +and linked at a fixed position with @code{-no-pie}. + +Here is a simple example with @code{gnatmake}: @quotation @@ -18925,12 +18941,12 @@ end STB; @end example @example -$ gnatmake stb -bargs -E +$ gnatmake stb -g -bargs -E -largs -no-pie $ stb -Execution terminated by unhandled exception -Exception name: CONSTRAINT_ERROR -Message: stb.adb:5 +Execution of stb terminated by unhandled exception +raised CONSTRAINT_ERROR : stb.adb:5 explicit raise +Load address: 0x400000 Call stack traceback locations: 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 @end example @@ -18939,32 +18955,22 @@ Call stack traceback locations: As we see the traceback lists a sequence of addresses for the unhandled exception @code{CONSTRAINT_ERROR} raised in procedure P1. It is easy to guess that this exception come from procedure P1. To translate these -addresses into the source lines where the calls appear, the -@code{addr2line} tool, described below, is invaluable. The use of this tool -requires the program to be compiled with debug information. +addresses into the source lines where the calls appear, the @code{addr2line} +tool needs to be invoked like this: @quotation @example -$ gnatmake -g stb -bargs -E -$ stb - -Execution terminated by unhandled exception -Exception name: CONSTRAINT_ERROR -Message: stb.adb:5 -Call stack traceback locations: -0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 - -$ addr2line --exe=stb 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 +$ addr2line -e stb 0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 -00401373 at d:/stb/stb.adb:5 -0040138B at d:/stb/stb.adb:10 -0040139C at d:/stb/stb.adb:14 -00401335 at d:/stb/b~stb.adb:104 -004011C4 at /build/.../crt1.c:200 -004011F1 at /build/.../crt1.c:222 -77E892A4 in ?? at ??:0 +d:/stb/stb.adb:5 +d:/stb/stb.adb:10 +d:/stb/stb.adb:14 +d:/stb/b~stb.adb:197 +crtexe.c:? +crtexe.c:? +??:0 @end example @end quotation @@ -18973,14 +18979,30 @@ The @code{addr2line} tool has several other useful options: @quotation -@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} +@multitable {xxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} +@item + +@code{-a --addresses} + +@tab + +to show the addresses alongside the line numbers + @item -@code{--functions} +@code{-f --functions} @tab -to get the function name corresponding to any location +to get the function name corresponding to a location + +@item + +@code{-p --pretty-print} + +@tab + +to print all the information on a single line @item @@ -18988,61 +19010,82 @@ to get the function name corresponding to any location @tab -to use the gnat decoding mode for the function names. -Note that for binutils version 2.9.x the option is -simply @code{--demangle}. +to use the GNAT decoding mode for the function names @end multitable @example -$ addr2line --exe=stb --functions --demangle=gnat 0x401373 0x40138b - 0x40139c 0x401335 0x4011c4 0x4011f1 +$ addr2line -e stb -a -f -p --demangle=gnat 0x401373 0x40138b + 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 -00401373 in stb.p1 at d:/stb/stb.adb:5 -0040138B in stb.p2 at d:/stb/stb.adb:10 -0040139C in stb at d:/stb/stb.adb:14 -00401335 in main at d:/stb/b~stb.adb:104 -004011C4 in <__mingw_CRTStartup> at /build/.../crt1.c:200 -004011F1 in <mainCRTStartup> at /build/.../crt1.c:222 +0x00401373: stb.p1 at d:/stb/stb.adb:5 +0x0040138B: stb.p2 at d:/stb/stb.adb:10 +0x0040139C: stb at d:/stb/stb.adb:14 +0x00401335: main at d:/stb/b~stb.adb:197 +0x004011c4: ?? at crtexe.c:? +0x004011f1: ?? at crtexe.c:? +0x77e892a4: ?? ??:0 @end example @end quotation -From this traceback we can see that the exception was raised in -@code{stb.adb} at line 5, which was reached from a procedure call in -@code{stb.adb} at line 10, and so on. The @code{b~std.adb} is the binder file, -which contains the call to the main program. -@ref{10e,,Running gnatbind}. The remaining entries are assorted runtime routines, -and the output will vary from platform to platform. +From this traceback we can see that the exception was raised in @code{stb.adb} +at line 5, which was reached from a procedure call in @code{stb.adb} at line +10, and so on. The @code{b~std.adb} is the binder file, which contains the +call to the main program. @ref{10e,,Running gnatbind}. The remaining entries are +assorted runtime routines and the output will vary from platform to platform. It is also possible to use @code{GDB} with these traceback addresses to debug the program. For example, we can break at a given code location, as reported in the stack traceback: -@quotation - @example $ gdb -nw stb + +(gdb) break *0x401373 +Breakpoint 1 at 0x401373: file stb.adb, line 5. @end example -@end quotation -Furthermore, this feature is not implemented inside Windows DLL. Only -the non-symbolic traceback is reported in this case. +It is important to note that the stack traceback addresses do not change when +debug information is included. This is particularly useful because it makes it +possible to release software without debug information (to minimize object +size), get a field report that includes a stack traceback whenever an internal +bug occurs, and then be able to retrieve the sequence of calls with the same +program compiled with debug information. -@quotation +However the @code{addr2line} tool does not work with Position-Independent Code +(PIC), the historical example being Windows DLLs, which nowadays encompasses +Position-Independent Executables (PIE) on recent Windows versions. + +In order to translate addresses into the source lines with Position-Independent +Executables on recent Windows versions, in other words without using the switch +@code{-no-pie} during linking, you need to use the @code{gnatsymbolize} tool +with @code{--load} instead of the @code{addr2line} tool. The main difference +is that you need to copy the Load Address output in the traceback ahead of the +sequence of addresses. And the default mode of @code{gnatsymbolize} is equivalent +to that of @code{addr2line} with the above switches, so none of them is needed: @example -(gdb) break *0x401373 -Breakpoint 1 at 0x401373: file stb.adb, line 5. -@end example -@end quotation +$ gnatmake stb -g -bargs -E +$ stb + +Execution of stb terminated by unhandled exception +raised CONSTRAINT_ERROR : stb.adb:5 explicit raise +Load address: 0x400000 +Call stack traceback locations: +0x401373 0x40138b 0x40139c 0x401335 0x4011c4 0x4011f1 0x77e892a4 + +$ gnatsymbolize --load stb 0x400000 0x401373 0x40138b 0x40139c 0x401335 + 0x4011c4 0x4011f1 0x77e892a4 -It is important to note that the stack traceback addresses -do not change when debug information is included. This is particularly useful -because it makes it possible to release software without debug information (to -minimize object size), get a field report that includes a stack traceback -whenever an internal bug occurs, and then be able to retrieve the sequence -of calls with the same program compiled with debug information. +0x00401373 Stb.P1 at stb.adb:5 +0x0040138B Stb.P2 at stb.adb:10 +0x0040139C Stb at stb.adb:14 +0x00401335 Main at b~stb.adb:197 +0x004011c4 __tmainCRTStartup at ??? +0x004011f1 mainCRTStartup at ??? +0x77e892a4 ??? at ??? +@end example @subsubheading Tracebacks From Exception Occurrences @@ -19090,8 +19133,8 @@ This program will output: @example $ stb -Exception name: CONSTRAINT_ERROR -Message: stb.adb:12 +raised CONSTRAINT_ERROR : stb.adb:12 range check failed +Load address: 0x400000 Call stack traceback locations: 0x4015e4 0x401633 0x401644 0x401461 0x4011c4 0x4011f1 0x77e892a4 @end example @@ -19100,17 +19143,16 @@ Call stack traceback locations: @subsubheading Tracebacks From Anywhere in a Program -It is also possible to retrieve a stack traceback from anywhere in a -program. For this you need to -use the @code{GNAT.Traceback} API. This package includes a procedure called -@code{Call_Chain} that computes a complete stack traceback, as well as useful -display procedures described below. It is not necessary to use the -@code{-E} @code{gnatbind} option in this case, because the stack traceback mechanism -is invoked explicitly. +It is also possible to retrieve a stack traceback from anywhere in a program. +For this you need to use the @code{GNAT.Traceback} API. This package includes a +procedure called @code{Call_Chain} that computes a complete stack traceback, as +well as useful display procedures described below. It is not necessary to use +the @code{-E} @code{gnatbind} option in this case, because the stack traceback +mechanism is invoked explicitly. -In the following example we compute a traceback at a specific location in -the program, and we display it using @code{GNAT.Debug_Utilities.Image} to -convert addresses to strings: +In the following example we compute a traceback at a specific location in the +program, and we display it using @code{GNAT.Debug_Utilities.Image} to convert +addresses to strings: @quotation @@ -19154,7 +19196,7 @@ end STB; @end example @example -$ gnatmake -g stb +$ gnatmake stb -g $ stb In STB.P1 : 16#0040_F1E4# 16#0040_14F2# 16#0040_170B# 16#0040_171C# @@ -19162,9 +19204,9 @@ In STB.P1 : 16#0040_F1E4# 16#0040_14F2# 16#0040_170B# 16#0040_171C# @end example @end quotation -You can then get further information by invoking the @code{addr2line} -tool as described earlier (note that the hexadecimal addresses -need to be specified in C format, with a leading ‘0x’). +You can then get further information by invoking the @code{addr2line} tool or +the @code{gnatsymbolize} tool as described earlier (note that the hexadecimal +addresses need to be specified in C format, with a leading ‘0x’). @geindex traceback @geindex symbolic @@ -19560,7 +19602,7 @@ The following is the subset of those switches that is most relevant: @table @asis -@item @code{--demangle[=@emph{style}]}, @code{--no-demangle} +@item @code{--demangle[=@var{style}]}, @code{--no-demangle} These options control whether symbol names should be demangled when printing output. The default is to demangle C++ symbols. The @@ -19576,9 +19618,9 @@ compiler, in particular Ada symbols generated by GNAT can be demangled using @table @asis -@item @code{-e @emph{function_name}} +@item @code{-e @var{function_name}} -The @code{-e @emph{function}} option tells @code{gprof} not to print +The @code{-e @var{function}} option tells @code{gprof} not to print information about the function @code{function_name} (and its children…) in the call graph. The function will still be listed as a child of any functions that call it, but its index number will be @@ -19592,9 +19634,9 @@ option. @table @asis -@item @code{-E @emph{function_name}} +@item @code{-E @var{function_name}} -The @code{-E @emph{function}} option works like the @code{-e} option, but +The @code{-E @var{function}} option works like the @code{-e} option, but execution time spent in the function (and children who were not called from anywhere else), will not be used to compute the percentages-of-time for the call graph. More than one @code{-E} option may be given; only one @@ -19606,9 +19648,9 @@ the call graph. More than one @code{-E} option may be given; only one @table @asis -@item @code{-f @emph{function_name}} +@item @code{-f @var{function_name}} -The @code{-f @emph{function}} option causes @code{gprof} to limit the +The @code{-f @var{function}} option causes @code{gprof} to limit the call graph to the function @code{function_name} and its children (and their children…). More than one @code{-f} option may be given; only one @code{function_name} may be indicated with each @code{-f} @@ -19620,9 +19662,9 @@ option. @table @asis -@item @code{-F @emph{function_name}} +@item @code{-F @var{function_name}} -The @code{-F @emph{function}} option works like the @code{-f} option, but +The @code{-F @var{function}} option works like the @code{-f} option, but only time spent in the function and its children (and their children…) will be used to determine total-time and percentages-of-time for the call graph. More than one @code{-F} option @@ -19921,7 +19963,7 @@ You should experiment to find the best level for your application. Since the precise set of optimizations done at each level will vary from release to release (and sometime from target to target), it is best to think of the optimization settings in general terms. -See the @emph{Options That Control Optimization} section in +See the `Options That Control Optimization' section in @cite{Using the GNU Compiler Collection (GCC)} for details about the @code{-O} settings and a number of @code{-f} options that @@ -19930,7 +19972,7 @@ individually enable or disable specific optimizations. Unlike some other compilation systems, @code{gcc} has been tested extensively at all optimization levels. There are some bugs which appear only with optimization turned on, but there have also been -bugs which show up only in @emph{unoptimized} code. Selecting a lower +bugs which show up only in `unoptimized' code. Selecting a lower level of optimization does not improve the reliability of the code generator, which in practice is highly reliable at all optimization levels. @@ -19979,7 +20021,7 @@ These are the most common cases: @itemize * @item -@emph{The ‘hopping Program Counter’:} Repeated @code{step} or @code{next} +`The ‘hopping Program Counter’:' Repeated @code{step} or @code{next} commands show the PC bouncing back and forth in the code. This may result from any of the following optimizations: @@ -19988,16 +20030,16 @@ the following optimizations: @itemize - @item -@emph{Common subexpression elimination:} using a single instance of code for a +`Common subexpression elimination:' using a single instance of code for a quantity that the source computes several times. As a result you may not be able to stop on what looks like a statement. @item -@emph{Invariant code motion:} moving an expression that does not change within a +`Invariant code motion:' moving an expression that does not change within a loop, to the beginning of the loop. @item -@emph{Instruction scheduling:} moving instructions so as to +`Instruction scheduling:' moving instructions so as to overlap loads and stores (typically) with other code, or in general to move computations of values closer to their uses. Often this causes you to pass an assignment statement without the assignment @@ -20008,16 +20050,16 @@ expected side-effects. @end itemize @item -@emph{The ‘big leap’:} More commonly known as @emph{cross-jumping}, in which +`The ‘big leap’:' More commonly known as `cross-jumping', in which two identical pieces of code are merged and the program counter suddenly jumps to a statement that is not supposed to be executed, simply because it (and the code following) translates to the same thing as the code -that @emph{was} supposed to be executed. This effect is typically seen in +that `was' supposed to be executed. This effect is typically seen in sequences that end in a jump, such as a @code{goto}, a @code{return}, or a @code{break} in a C @code{switch} statement. @item -@emph{The ‘roving variable’:} The symptom is an unexpected value in a variable. +`The ‘roving variable’:' The symptom is an unexpected value in a variable. There are various reasons for this effect: @@ -20053,7 +20095,7 @@ calling subprogram to verify that the value observed is explainable from other values (one must apply the procedure recursively to those other values); or re-running the code and stopping a little earlier (perhaps before the call) and stepping to better see how the variable obtained -the value in question; or continuing to step @emph{from} the point of the +the value in question; or continuing to step `from' the point of the strange value to see if code motion had simply moved the variable’s assignments later. @end itemize @@ -20098,7 +20140,7 @@ within it; the subprogram is small and optimization level @code{-O2} is specified; optimization level @code{-O3} is specified. @end itemize -Calls to subprograms in @emph{with}ed units are normally not inlined. +Calls to subprograms in `with'ed units are normally not inlined. To achieve actual inlining (that is, replacement of the call by the code in the body of the subprogram), the following conditions must all be true: @@ -20420,7 +20462,7 @@ to work. Examples of switches in this category are @code{-funroll-loops} and the various target-specific @code{-m} options (in particular, it has been observed that @code{-march=xxx} can significantly improve performance on appropriate machines). For full details of these switches, see -the @emph{Submodel Options} section in the @emph{Hardware Models and Configurations} +the `Submodel Options' section in the `Hardware Models and Configurations' chapter of @cite{Using the GNU Compiler Collection (GCC)}. @node Optimization and Strict Aliasing,Aliased Variables and Optimization,Other Optimization Switches,Performance Considerations @@ -20863,7 +20905,7 @@ If @code{Text_IO} must be used, note that by default output to the standard output and standard error files is unbuffered (this provides better behavior when output statements are used for debugging, or if the progress of a program is observed by tracking the output, e.g. by -using the Unix @emph{tail -f} command to watch redirected output). +using the Unix `tail -f' command to watch redirected output). If you are generating large volumes of output with @code{Text_IO} and performance is an important factor, use a designated file instead @@ -21174,7 +21216,7 @@ The three modes are: @itemize * @item -@emph{Use base type for intermediate operations} (@code{STRICT}) +`Use base type for intermediate operations' (@code{STRICT}) In this mode, all intermediate results for predefined arithmetic operators are computed using the base type, and the result must @@ -21184,7 +21226,7 @@ enabled) or the execution is erroneous (if overflow checks are suppressed). This is the normal default mode. @item -@emph{Most intermediate overflows avoided} (@code{MINIMIZED}) +`Most intermediate overflows avoided' (@code{MINIMIZED}) In this mode, the compiler attempts to avoid intermediate overflows by using a larger integer type, typically @code{Long_Long_Integer}, @@ -21217,12 +21259,12 @@ out of the range of @code{Long_Long_Integer} even though the final result is in range and the precondition is True (from a mathematical point of view). In such a case, operating in this mode, an overflow occurs for the intermediate computation (which is why this mode -says @emph{most} intermediate overflows are avoided). In this case, +says `most' intermediate overflows are avoided). In this case, an exception is raised if overflow checks are enabled, and the execution is erroneous if overflow checks are suppressed. @item -@emph{All intermediate overflows avoided} (@code{ELIMINATED}) +`All intermediate overflows avoided' (@code{ELIMINATED}) In this mode, the compiler avoids all intermediate overflows by using arbitrary precision arithmetic as required. In this @@ -21509,8 +21551,8 @@ version 7.0.1 of GNAT onwards. The GNAT-specific aspect @code{Dimension_System} allows you to define a system of units; the aspect @code{Dimension} then allows the user to declare dimensioned quantities within a given system. -(These aspects are described in the @emph{Implementation Defined Aspects} -chapter of the @emph{GNAT Reference Manual}). +(These aspects are described in the `Implementation Defined Aspects' +chapter of the `GNAT Reference Manual'). The major advantage of this model is that it does not require the declaration of multiple operators for all possible combinations of types: it is only necessary @@ -21707,9 +21749,9 @@ Final velocity: 98.10 m.s**(-1) @geindex Dimensioned subtype @end quotation -The type @code{Mks_Type} is said to be a @emph{dimensionable type} since it has a +The type @code{Mks_Type} is said to be a `dimensionable type' since it has a @code{Dimension_System} aspect, and the subtypes @code{Length}, @code{Mass}, etc., -are said to be @emph{dimensioned subtypes} since each one has a @code{Dimension} +are said to be `dimensioned subtypes' since each one has a @code{Dimension} aspect. @quotation @@ -21723,8 +21765,8 @@ aspect. The @code{Dimension} aspect of a dimensioned subtype @code{S} defines a mapping from the base type’s Unit_Names to integer (or, more generally, rational) -values. This mapping is the @emph{dimension vector} (also referred to as the -@emph{dimensionality}) for that subtype, denoted by @code{DV(S)}, and thus for each +values. This mapping is the `dimension vector' (also referred to as the +`dimensionality') for that subtype, denoted by @code{DV(S)}, and thus for each object of that subtype. Intuitively, the value specified for each @code{Unit_Name} is the exponent associated with that unit; a zero value means that the unit is not used. For example: @@ -21750,34 +21792,34 @@ dimension vectors of its components, with compile-time dimensionality checks that help prevent mismatches such as using an @code{Acceleration} where a @code{Length} is required. -The dimension vector of the result of an arithmetic expression @emph{expr}, or -@code{DV(@emph{expr})}, is defined as follows, assuming conventional +The dimension vector of the result of an arithmetic expression `expr', or +@code{DV(@var{expr})}, is defined as follows, assuming conventional mathematical definitions for the vector operations that are used: @itemize * @item -If @emph{expr} is of the type @emph{universal_real}, or is not of a dimensioned subtype, -then @emph{expr} is dimensionless; @code{DV(@emph{expr})} is the empty vector. +If `expr' is of the type `universal_real', or is not of a dimensioned subtype, +then `expr' is dimensionless; @code{DV(@var{expr})} is the empty vector. @item -@code{DV(@emph{op expr})}, where @emph{op} is a unary operator, is @code{DV(@emph{expr})} +@code{DV(@var{op expr})}, where `op' is a unary operator, is @code{DV(@var{expr})} @item -@code{DV(@emph{expr1 op expr2})} where @emph{op} is “+†or “-†is @code{DV(@emph{expr1})} -provided that @code{DV(@emph{expr1})} = @code{DV(@emph{expr2})}. +@code{DV(@var{expr1 op expr2})} where `op' is “+†or “-†is @code{DV(@var{expr1})} +provided that @code{DV(@var{expr1})} = @code{DV(@var{expr2})}. If this condition is not met then the construct is illegal. @item -@code{DV(@emph{expr1} * @emph{expr2})} is @code{DV(@emph{expr1})} + @code{DV(@emph{expr2})}, -and @code{DV(@emph{expr1} / @emph{expr2})} = @code{DV(@emph{expr1})} - @code{DV(@emph{expr2})}. -In this context if one of the @emph{expr}s is dimensionless then its empty +@code{DV(@var{expr1} * @var{expr2})} is @code{DV(@var{expr1})} + @code{DV(@var{expr2})}, +and @code{DV(@var{expr1} / @var{expr2})} = @code{DV(@var{expr1})} - @code{DV(@var{expr2})}. +In this context if one of the `expr's is dimensionless then its empty dimension vector is treated as @code{(others => 0)}. @item -@code{DV(@emph{expr} ** @emph{power})} is @emph{power} * @code{DV(@emph{expr})}, -provided that @emph{power} is a static rational value. If this condition is not +@code{DV(@var{expr} ** @var{power})} is `power' * @code{DV(@var{expr})}, +provided that `power' is a static rational value. If this condition is not met then the construct is illegal. @end itemize @@ -21787,7 +21829,7 @@ combine a dimensioned and dimensionless value. Thus an expression such as @code{Acceleration}. The dimensionality checks for relationals use the same rules as -for “+†and “-“, except when comparing to a literal; thus +for “+†and “-â€, except when comparing to a literal; thus @quotation @@ -21817,17 +21859,17 @@ acc > 10.0 is accepted with a warning. Analogously a conditional expression requires the same dimension vector for each branch (with no exception for literals). -The dimension vector of a type conversion @code{T(@emph{expr})} is defined +The dimension vector of a type conversion @code{T(@var{expr})} is defined as follows, based on the nature of @code{T}: @itemize * @item -If @code{T} is a dimensioned subtype then @code{DV(T(@emph{expr}))} is @code{DV(T)} -provided that either @emph{expr} is dimensionless or -@code{DV(T)} = @code{DV(@emph{expr})}. The conversion is illegal -if @emph{expr} is dimensioned and @code{DV(@emph{expr})} /= @code{DV(T)}. +If @code{T} is a dimensioned subtype then @code{DV(T(@var{expr}))} is @code{DV(T)} +provided that either `expr' is dimensionless or +@code{DV(T)} = @code{DV(@var{expr})}. The conversion is illegal +if `expr' is dimensioned and @code{DV(@var{expr})} /= @code{DV(T)}. Note that vector equality does not require that the corresponding Unit_Names be the same. @@ -21839,9 +21881,9 @@ a length in inches (with a suitable conversion factor) but cannot be converted, for example, to a mass in pounds. @item -If @code{T} is the base type for @emph{expr} (and the dimensionless root type of -the dimension system), then @code{DV(T(@emph{expr}))} is @code{DV(expr)}. -Thus, if @emph{expr} is of a dimensioned subtype of @code{T}, the conversion may +If @code{T} is the base type for `expr' (and the dimensionless root type of +the dimension system), then @code{DV(T(@var{expr}))} is @code{DV(expr)}. +Thus, if `expr' is of a dimensioned subtype of @code{T}, the conversion may be regarded as a “view conversion†that preserves dimensionality. This rule makes it possible to write generic code that can be instantiated @@ -21853,13 +21895,13 @@ dimensionality. @item Otherwise (i.e., @code{T} is neither a dimensioned subtype nor a dimensionable -base type), @code{DV(T(@emph{expr}))} is the empty vector. Thus a dimensioned +base type), @code{DV(T(@var{expr}))} is the empty vector. Thus a dimensioned value can be explicitly converted to a non-dimensioned subtype, which of course then escapes dimensionality analysis. @end itemize -The dimension vector for a type qualification @code{T'(@emph{expr})} is the same -as for the type conversion @code{T(@emph{expr})}. +The dimension vector for a type qualification @code{T'(@var{expr})} is the same +as for the type conversion @code{T(@var{expr})}. An assignment statement @@ -22033,16 +22075,16 @@ where: @itemize * @item -@emph{Index} is a number associated with each task. +`Index' is a number associated with each task. @item -@emph{Task Name} is the name of the task analyzed. +`Task Name' is the name of the task analyzed. @item -@emph{Stack Size} is the maximum size for the stack. +`Stack Size' is the maximum size for the stack. @item -@emph{Stack Usage} is the measure done by the stack analyzer. +`Stack Usage' is the measure done by the stack analyzer. In order to prevent overflow, the stack is not entirely analyzed, and it’s not possible to know exactly how much has actually been used. @@ -22373,7 +22415,7 @@ For exception handling, either or both of two models are supplied: @itemize * @item -@strong{Zero-Cost Exceptions} (“ZCXâ€), +`Zero-Cost Exceptions' (“ZCXâ€), which uses binder-generated tables that are interrogated at run time to locate a handler. @@ -22382,7 +22424,7 @@ are interrogated at run time to locate a handler. @geindex SJLJ (setjmp/longjmp Exception Model) @item -@strong{setjmp / longjmp} (‘SJLJ’), +`setjmp / longjmp' (‘SJLJ’), which uses dynamically-set data to establish the set of handlers @end itemize @@ -22528,7 +22570,7 @@ contain a complete source and binary subdirectory. The detailed description below explains the differences between the different libraries in terms of their thread support. -The default run-time library (when GNAT is installed) is @emph{rts-native}. +The default run-time library (when GNAT is installed) is `rts-native'. This default run-time is selected by the means of soft links. For example on x86-linux: @@ -22572,7 +22614,7 @@ ADAINCLUDE ADALIB rts-native rts-sjlj (Upper-case names and dotted/dashed arrows represent soft links) @end example -If the @emph{rts-sjlj} library is to be selected on a permanent basis, +If the `rts-sjlj' library is to be selected on a permanent basis, these soft links can be modified with the following commands: @quotation @@ -23232,12 +23274,12 @@ on the stack by the caller from right to left. The callee (and not the caller) is in charge of cleaning the stack on routine exit. In addition, the name of a routine with @code{Stdcall} calling convention is mangled by adding a leading underscore (as for the @code{C} calling convention) and a -trailing @code{@@@emph{nn}}, where @code{nn} is the overall size (in +trailing @code{@@@var{nn}}, where @code{nn} is the overall size (in bytes) of the parameters passed to the routine. The name to use on the Ada side when importing a C routine with a @code{Stdcall} calling convention is the name of the C routine. The leading -underscore and trailing @code{@@@emph{nn}} are added automatically by +underscore and trailing @code{@@@var{nn}} are added automatically by the compiler. For instance the Win32 function: @quotation @@ -23284,10 +23326,10 @@ pragma Import (Stdcall, Get_Val, Link_Name => "retrieve_val"); then the imported routine is @code{retrieve_val}, that is, there is no decoration at all. No leading underscore and no Stdcall suffix -@code{@@@emph{nn}}. +@code{@@@var{nn}}. This is especially important as in some special cases a DLL’s entry -point name lacks a trailing @code{@@@emph{nn}} while the exported +point name lacks a trailing @code{@@@var{nn}} while the exported name generated for a call has it. It is also possible to import variables defined in a DLL by using an @@ -23588,16 +23630,16 @@ EXPORTS @table @asis -@item @emph{LIBRARY name} +@item `LIBRARY name' This section, which is optional, gives the name of the DLL. -@item @emph{DESCRIPTION string} +@item `DESCRIPTION string' This section, which is optional, gives a description string that will be embedded in the import library. -@item @emph{EXPORTS} +@item `EXPORTS' This section gives the list of exported symbols (procedures, functions or variables). For instance in the case of @code{API.dll} the @code{EXPORTS} @@ -23610,7 +23652,7 @@ EXPORTS @end example @end table -Note that you must specify the correct suffix (@code{@@@emph{nn}}) +Note that you must specify the correct suffix (@code{@@@var{nn}}) (see @ref{1d2,,Windows Calling Conventions}) for a Stdcall calling convention function in the exported symbols list. @@ -23631,11 +23673,11 @@ $ dlltool API.dll -z API.def --export-all-symbols @end example Note that if some routines in the DLL have the @code{Stdcall} convention -(@ref{1d2,,Windows Calling Conventions}) with stripped @code{@@@emph{nn}} +(@ref{1d2,,Windows Calling Conventions}) with stripped @code{@@@var{nn}} suffix then you’ll have to edit @code{api.def} to add it, and specify @code{-k} to @code{gnatdll} when creating the import library. -Here are some hints to find the right @code{@@@emph{nn}} suffix. +Here are some hints to find the right @code{@@@var{nn}} suffix. @itemize - @@ -23717,8 +23759,8 @@ See the Microsoft documentation for further details about the usage of @geindex building There is nothing specific to Windows in the build process. -See the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User’s Guide}. +See the `Library Projects' section in the `GNAT Project Manager' +chapter of the `GPRbuild User’s Guide'. Due to a system limitation, it is not possible under Windows to create threads when inside the @code{DllMain} routine which is used for auto-initialization @@ -23853,8 +23895,8 @@ Note that a relocatable DLL stripped using the @code{strip} binutils tool will not be relocatable anymore. To build a DLL without debug information pass @code{-largs -s} to @code{gnatdll}. This restriction does not apply to a DLL built using a Library Project. -See the @emph{Library Projects} section in the @emph{GNAT Project Manager} -chapter of the @emph{GPRbuild User’s Guide}. +See the `Library Projects' section in the `GNAT Project Manager' +chapter of the `GPRbuild User’s Guide'. @c Limitations_When_Using_Ada_DLLs_from Ada: @@ -24169,7 +24211,7 @@ You may specify any of the following switches to @code{gnatdll}: @table @asis -@item @code{-a[@emph{address}]} +@item @code{-a[`address']} Build a non-relocatable DLL at @code{address}. If @code{address} is not specified the default address @code{0x11000000} will be used. By default, @@ -24178,20 +24220,20 @@ advise the reader to build relocatable DLL. @geindex -b (gnatdll) -@item @code{-b @emph{address}} +@item @code{-b `address'} Set the relocatable DLL base address. By default the address is @code{0x11000000}. @geindex -bargs (gnatdll) -@item @code{-bargs @emph{opts}} +@item @code{-bargs `opts'} Binder options. Pass @code{opts} to the binder. @geindex -d (gnatdll) -@item @code{-d @emph{dllfile}} +@item @code{-d `dllfile'} @code{dllfile} is the name of the DLL. This switch must be present for @code{gnatdll} to do anything. The name of the generated import library is @@ -24205,7 +24247,7 @@ file used is @code{xyz.def}. @geindex -e (gnatdll) -@item @code{-e @emph{deffile}} +@item @code{-e `deffile'} @code{deffile} is the name of the definition file. @@ -24227,7 +24269,7 @@ Help mode. Displays @code{gnatdll} switch usage information. @geindex -I (gnatdll) -@item @code{-I@emph{dir}} +@item @code{-I`dir'} Direct @code{gnatdll} to search the @code{dir} directory for source and object files needed to build the DLL. @@ -24237,16 +24279,16 @@ object files needed to build the DLL. @item @code{-k} -Removes the @code{@@@emph{nn}} suffix from the import library’s exported +Removes the @code{@@@var{nn}} suffix from the import library’s exported names, but keeps them for the link names. You must specify this option if you want to use a @code{Stdcall} function in a DLL for which -the @code{@@@emph{nn}} suffix has been removed. This is the case for most +the @code{@@@var{nn}} suffix has been removed. This is the case for most of the Windows NT DLL for example. This option has no effect when @code{-n} option is specified. @geindex -l (gnatdll) -@item @code{-l @emph{file}} +@item @code{-l `file'} The list of ALI and object files used to build the DLL are listed in @code{file}, instead of being given in the command line. Each line in @@ -24272,7 +24314,7 @@ Verbose mode. Display extra information. @geindex -largs (gnatdll) -@item @code{-largs @emph{opts}} +@item @code{-largs `opts'} Linker options. Pass @code{opts} to the linker. @end table @@ -24406,7 +24448,7 @@ $ dlltool [`switches`] @table @asis -@item @code{--base-file @emph{basefile}} +@item @code{--base-file `basefile'} Read the base file @code{basefile} generated by the linker. This switch is used to create a relocatable DLL. @@ -24417,7 +24459,7 @@ is used to create a relocatable DLL. @table @asis -@item @code{--def @emph{deffile}} +@item @code{--def `deffile'} Read the definition file. @end table @@ -24427,7 +24469,7 @@ Read the definition file. @table @asis -@item @code{--dllname @emph{name}} +@item @code{--dllname `name'} Gives the name of the DLL. This switch is used to embed the name of the DLL in the static import library generated by @code{dlltool} with switch @@ -24441,7 +24483,7 @@ DLL in the static import library generated by @code{dlltool} with switch @item @code{-k} -Kill @code{@@@emph{nn}} from exported names +Kill @code{@@@var{nn}} from exported names (@ref{1d2,,Windows Calling Conventions} for a discussion about @code{Stdcall}-style symbols). @end table @@ -24461,7 +24503,7 @@ Prints the @code{dlltool} switches with a concise description. @table @asis -@item @code{--output-exp @emph{exportfile}} +@item @code{--output-exp `exportfile'} Generate an export file @code{exportfile}. The export file contains the export table (list of symbols in the DLL) and is used to create the DLL. @@ -24472,7 +24514,7 @@ export table (list of symbols in the DLL) and is used to create the DLL. @table @asis -@item @code{--output-lib @emph{libfile}} +@item @code{--output-lib `libfile'} Generate a static import library @code{libfile}. @end table @@ -24492,7 +24534,7 @@ Verbose mode. @table @asis -@item @code{--as @emph{assembler-name}} +@item @code{--as `assembler-name'} Use @code{assembler-name} as the assembler. The default is @code{as}. @end table @@ -24967,7 +25009,7 @@ $ main @end example @item -Use the Windows @emph{Task Manager} to find the process ID. Let’s say +Use the Windows `Task Manager' to find the process ID. Let’s say that the process PID for @code{main.exe} is 208. @item @@ -25019,7 +25061,7 @@ approach to debug a program as described in It is possible to specify the program stack size at link time. On modern versions of Windows, starting with XP, this is mostly useful to set the size of the main stack (environment task). The other task stacks are set with pragma -Storage_Size or with the @emph{gnatbind -d} command. +Storage_Size or with the `gnatbind -d' command. Since older versions of Windows (2000, NT4, etc.) do not allow setting the reserve size of individual tasks, the link-time stack size applies to all @@ -25268,7 +25310,7 @@ in the Unix group @code{_developer}. @geindex Binder output (example) This Appendix displays the source code for the output file -generated by @emph{gnatbind} for a simple ‘Hello World’ program. +generated by `gnatbind' for a simple ‘Hello World’ program. Comments have been added for clarification purposes. @example @@ -26047,13 +26089,13 @@ GNAT, either automatically or with explicit programming features. @section Elaboration Code -Ada defines the term @emph{execution} as the process by which a construct achieves -its run-time effect. This process is also referred to as @strong{elaboration} for -declarations and @emph{evaluation} for expressions. +Ada defines the term `execution' as the process by which a construct achieves +its run-time effect. This process is also referred to as `elaboration' for +declarations and `evaluation' for expressions. The execution model in Ada allows for certain sections of an Ada program to be executed prior to execution of the program itself, primarily with the intent of -initializing data. These sections are referred to as @strong{elaboration code}. +initializing data. These sections are referred to as `elaboration code'. Elaboration code is executed as follows: @@ -26070,7 +26112,7 @@ partition. @item The environment task executes all elaboration code (if available) for all units within that partition. This code is said to be executed at -@strong{elaboration time}. +`elaboration time'. @item The environment task executes the Ada program (if available) for that @@ -26083,16 +26125,16 @@ In addition to the Ada terminology, this appendix defines the following terms: @itemize * @item -@emph{Invocation} +`Invocation' The act of calling a subprogram, instantiating a generic, or activating a task. @item -@emph{Scenario} +`Scenario' A construct that is elaborated or invoked by elaboration code is referred to -as an @emph{elaboration scenario} or simply a @strong{scenario}. GNAT recognizes the +as an `elaboration scenario' or simply a `scenario'. GNAT recognizes the following scenarios: @@ -26112,10 +26154,10 @@ Instantiations of generic templates @end itemize @item -@emph{Target} +`Target' -A construct elaborated by a scenario is referred to as @emph{elaboration target} -or simply @strong{target}. GNAT recognizes the following targets: +A construct elaborated by a scenario is referred to as `elaboration target' +or simply `target'. GNAT recognizes the following targets: @itemize - @@ -26143,7 +26185,7 @@ Elaboration code may appear in two distinct contexts: @itemize * @item -@emph{Library level} +`Library level' A scenario appears at the library level when it is encapsulated by a package [body] compilation unit, ignoring any other package [body] declarations in @@ -26167,7 +26209,7 @@ given above. As a result, the call to @code{Server.Func} will be invoked when the spec of unit @code{Client} is elaborated. @item -@emph{Package body statements} +`Package body statements' A scenario appears within the statement sequence of a package body when it is bounded by the region starting from the @code{begin} keyword of the package body @@ -26196,7 +26238,7 @@ elaborated. The sequence by which the elaboration code of all units within a partition is -executed is referred to as @strong{elaboration order}. +executed is referred to as `elaboration order'. Within a single unit, elaboration code is executed in sequential order. @@ -26260,7 +26302,7 @@ factors: @itemize * @item -@emph{with}ed units +`with'ed units @item parent units @@ -26313,7 +26355,7 @@ procedure Main is begin null; end Main; @end quotation The following elaboration order exhibits a fundamental problem referred to as -@emph{access-before-elaboration} or simply @strong{ABE}. +`access-before-elaboration' or simply `ABE'. @quotation @@ -26353,7 +26395,7 @@ body of Main Ada states that a total elaboration order must exist, but it does not define what this order is. A compiler is thus tasked with choosing a suitable -elaboration order which satisfies the dependencies imposed by @emph{with} clauses, +elaboration order which satisfies the dependencies imposed by `with' clauses, unit categorization, elaboration-control pragmas, and invocations performed in elaboration code. Ideally an order that avoids ABE problems should be chosen, however a compiler may not always find such an order due to complications with @@ -26371,15 +26413,15 @@ provides three lines of defense: @itemize * @item -@emph{Static semantics} +`Static semantics' Static semantic rules restrict the possible choice of elaboration order. For -instance, if unit Client @emph{with}s unit Server, then the spec of Server is +instance, if unit Client `with's unit Server, then the spec of Server is always elaborated prior to Client. The same principle applies to child units - the spec of a parent unit is always elaborated prior to the child unit. @item -@emph{Dynamic semantics} +`Dynamic semantics' Dynamic checks are performed at run time, to ensure that a target is elaborated prior to a scenario that invokes it, thus avoiding ABE problems. @@ -26390,19 +26432,19 @@ restrictions apply: @itemize - @item -@emph{Restrictions on calls} +`Restrictions on calls' An entry, operator, or subprogram can be called from elaboration code only when the corresponding body has been elaborated. @item -@emph{Restrictions on instantiations} +`Restrictions on instantiations' A generic unit can be instantiated by elaboration code only when the corresponding body has been elaborated. @item -@emph{Restrictions on task activation} +`Restrictions on task activation' A task can be activated by elaboration code only when the body of the associated task type has been elaborated. @@ -26410,11 +26452,11 @@ associated task type has been elaborated. The restrictions above can be summarized by the following rule: -@emph{If a target has a body, then this body must be elaborated prior to the -scenario that invokes the target.} +`If a target has a body, then this body must be elaborated prior to the +scenario that invokes the target.' @item -@emph{Elaboration control} +`Elaboration control' Pragmas are provided for the programmer to specify the desired elaboration order. @@ -26432,7 +26474,7 @@ the desired elaboration order and avoiding ABE problems altogether. @itemize * @item -@emph{Packages without a body} +`Packages without a body' A library package which does not require a completing body does not suffer from ABE problems. @@ -26459,7 +26501,7 @@ any ABE problems. @itemize * @item -@emph{pragma Pure} +`pragma Pure' Pragma @code{Pure} places sufficient restrictions on a unit to guarantee that no scenario within the unit can result in an ABE problem. @@ -26471,7 +26513,7 @@ scenario within the unit can result in an ABE problem. @itemize * @item -@emph{pragma Preelaborate} +`pragma Preelaborate' Pragma @code{Preelaborate} is slightly less restrictive than pragma @code{Pure}, but still strong enough to prevent ABE problems within a unit. @@ -26483,7 +26525,7 @@ but still strong enough to prevent ABE problems within a unit. @itemize * @item -@emph{pragma Elaborate_Body} +`pragma Elaborate_Body' Pragma @code{Elaborate_Body} requires that the body of a unit is elaborated immediately after its spec. This restriction guarantees that no client @@ -26524,7 +26566,7 @@ spec of Client @end example because the spec of @code{Server} must be elaborated prior to @code{Client} by -virtue of the @emph{with} clause, and in addition the body of @code{Server} must be +virtue of the `with' clause, and in addition the body of @code{Server} must be elaborated immediately after the spec of @code{Server}. Removing pragma @code{Elaborate_Body} could result in the following incorrect @@ -26555,10 +26597,10 @@ depend on. @itemize * @item -@emph{pragma Elaborate (Unit)} +`pragma Elaborate (Unit)' Pragma @code{Elaborate} can be placed in the context clauses of a unit, after a -@emph{with} clause. It guarantees that both the spec and body of its argument will +`with' clause. It guarantees that both the spec and body of its argument will be elaborated prior to the unit with the pragma. Note that other unrelated units may be elaborated in between the spec and the body. @@ -26613,12 +26655,12 @@ has not been elaborated yet. @itemize * @item -@emph{pragma Elaborate_All (Unit)} +`pragma Elaborate_All (Unit)' Pragma @code{Elaborate_All} is placed in the context clauses of a unit, after -a @emph{with} clause. It guarantees that both the spec and body of its argument +a `with' clause. It guarantees that both the spec and body of its argument will be elaborated prior to the unit with the pragma, as well as all units -@emph{with}ed by the spec and body of the argument, recursively. Note that other +`with'ed by the spec and body of the argument, recursively. Note that other unrelated units may be elaborated in between the spec and the body. @example @@ -26704,10 +26746,10 @@ elaborated yet. All pragmas shown above can be summarized by the following rule: -@emph{If a client unit elaborates a server target directly or indirectly, then if +`If a client unit elaborates a server target directly or indirectly, then if the server unit requires a body and does not have pragma Pure, Preelaborate, or Elaborate_Body, then the client unit should have pragma Elaborate or -Elaborate_All for the server unit.} +Elaborate_All for the server unit.' If the rule outlined above is not followed, then a program may fall in one of the following states: @@ -26716,19 +26758,19 @@ the following states: @itemize * @item -@emph{No elaboration order exists} +`No elaboration order exists' In this case a compiler must diagnose the situation, and refuse to build an executable program. @item -@emph{One or more incorrect elaboration orders exist} +`One or more incorrect elaboration orders exist' In this case a compiler can build an executable program, but @code{Program_Error} will be raised when the program is run. @item -@emph{Several elaboration orders exist, some correct, some incorrect} +`Several elaboration orders exist, some correct, some incorrect' In this case the programmer has not controlled the elaboration order. As a result, a compiler may or may not pick one of the correct orders, and the @@ -26737,7 +26779,7 @@ worst possible state because the program may fail on another compiler, or even another version of the same compiler. @item -@emph{One or more correct orders exist} +`One or more correct orders exist' In this case a compiler can build an executable program, and the program is run successfully. This state may be guaranteed by following the outlined @@ -26763,7 +26805,7 @@ elaboration order and to diagnose elaboration problems. @itemize * @item -@emph{Dynamic elaboration model} +`Dynamic elaboration model' This is the most permissive of the three elaboration models and emulates the behavior specified by the Ada Reference Manual. When the dynamic model is in @@ -26785,7 +26827,7 @@ GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios that invoke internal targets. In addition, GNAT generates run-time checks for all external targets and for all scenarios that may exhibit ABE problems. -The elaboration order is obtained by honoring all @emph{with} clauses, purity and +The elaboration order is obtained by honoring all `with' clauses, purity and preelaborability of units, and elaboration-control pragmas. The dynamic model attempts to take all invocations in elaboration code into account. If an invocation leads to a circularity, GNAT ignores the invocation based on the @@ -26801,7 +26843,7 @@ The dynamic model is enabled with compiler switch @code{-gnatE}. @itemize * @item -@emph{Static elaboration model} +`Static elaboration model' This is the middle ground of the three models. When the static model is in effect, GNAT makes the following assumptions: @@ -26822,7 +26864,7 @@ GNAT performs extensive diagnostics on a unit-by-unit basis for all scenarios that invoke internal targets. In addition, GNAT generates run-time checks for all external targets and for all scenarios that may exhibit ABE problems. -The elaboration order is obtained by honoring all @emph{with} clauses, purity and +The elaboration order is obtained by honoring all `with' clauses, purity and preelaborability of units, presence of elaboration-control pragmas, and all invocations in elaboration code. An order obtained using the static model is guaranteed to be ABE problem-free, excluding dispatching calls and @@ -26837,7 +26879,7 @@ The static model is the default model in GNAT. @itemize * @item -@emph{SPARK elaboration model} +`SPARK elaboration model' This is the most conservative of the three models and enforces the SPARK rules of elaboration as defined in the SPARK Reference Manual, section 7.7. @@ -26854,7 +26896,7 @@ The SPARK model is enabled with compiler switch @code{-gnatd.v}. @itemize * @item -@emph{Legacy elaboration models} +`Legacy elaboration models' In addition to the three elaboration models outlined above, GNAT provides the following legacy models: @@ -26890,7 +26932,7 @@ however the following rules must be observed: @itemize * @item -A client unit compiled with the dynamic model can only @emph{with} a server unit +A client unit compiled with the dynamic model can only `with' a server unit that meets at least one of the following criteria: @@ -26940,8 +26982,8 @@ conservative, or a particular scenario may not be invoked due conditional execution. The warnings can be suppressed selectively with @code{pragma Warnings (Off)} or globally with compiler switch @code{-gnatwL}. -A @emph{guaranteed ABE} arises when the body of a target is not elaborated early -enough, and causes @emph{all} scenarios that directly invoke the target to fail. +A `guaranteed ABE' arises when the body of a target is not elaborated early +enough, and causes `all' scenarios that directly invoke the target to fail. @quotation @@ -26973,8 +27015,8 @@ the declaration of @code{Val}. This invokes function @code{ABE}, however the bod @end example @end quotation -A @emph{conditional ABE} arises when the body of a target is not elaborated early -enough, and causes @emph{some} scenarios that directly invoke the target to fail. +A `conditional ABE' arises when the body of a target is not elaborated early +enough, and causes `some' scenarios that directly invoke the target to fail. @quotation @@ -27063,9 +27105,9 @@ rules. @section Elaboration Circularities -An @strong{elaboration circularity} occurs whenever the elaboration of a set of +An `elaboration circularity' occurs whenever the elaboration of a set of units enters a deadlocked state, where each unit is waiting for another unit -to be elaborated. This situation may be the result of improper use of @emph{with} +to be elaborated. This situation may be the result of improper use of `with' clauses, elaboration-control pragmas, or invocations in elaboration code. The following example exhibits an elaboration circularity. @@ -27173,7 +27215,7 @@ too much modification, especially in the case of complex legacy code. When faced with an elaboration circularity, the programmer should also consider the tactics given in the suggestions section of the circularity diagnostic. -Depending on the units involved in the circularity, their @emph{with} clauses, +Depending on the units involved in the circularity, their `with' clauses, purity, preelaborability, presence of elaboration-control pragmas and invocations at elaboration time, the binder may suggest one or more of the following tactics to eliminate the circularity: @@ -27226,7 +27268,7 @@ Prevents a set of units from being elaborated. @item The removal of the pragma will not eliminate the semantic effects of the -pragma. In other words, the argument of the pragma along with its @emph{with} +pragma. In other words, the argument of the pragma along with its `with' closure will still be elaborated prior to the unit containing the pragma. @item @@ -27469,20 +27511,20 @@ information depending on the elaboration model in effect. @itemize - @item -@emph{Dynamic model} +`Dynamic model' GNAT will indicate missing @code{Elaborate} and @code{Elaborate_All} pragmas for all library-level scenarios within the partition. @item -@emph{Static model} +`Static model' GNAT will indicate all scenarios invoked during elaboration. In addition, it will provide detailed traceback when an implicit @code{Elaborate} or @code{Elaborate_All} pragma is generated. @item -@emph{SPARK model} +`SPARK model' GNAT will indicate how an elaboration requirement is met by the context of a unit. This diagnostic requires compiler switch @code{-gnatd.v}. @@ -27885,7 +27927,7 @@ pre-processor) documentation for further information. @display -@emph{Register names}@w{ } +`Register names'@w{ } @display gcc / @code{as}: Prefix with ‘%’; for example @code{%eax}@w{ } Intel: No extra punctuation; for example @code{eax}@w{ } @@ -27896,7 +27938,7 @@ Intel: No extra punctuation; for example @code{eax}@w{ } @display -@emph{Immediate operand}@w{ } +`Immediate operand'@w{ } @display gcc / @code{as}: Prefix with ‘$’; for example @code{$4}@w{ } Intel: No extra punctuation; for example @code{4}@w{ } @@ -27907,7 +27949,7 @@ Intel: No extra punctuation; for example @code{4}@w{ } @display -@emph{Address}@w{ } +`Address'@w{ } @display gcc / @code{as}: Prefix with ‘$’; for example @code{$loc}@w{ } Intel: No extra punctuation; for example @code{loc}@w{ } @@ -27918,7 +27960,7 @@ Intel: No extra punctuation; for example @code{loc}@w{ } @display -@emph{Memory contents}@w{ } +`Memory contents'@w{ } @display gcc / @code{as}: No extra punctuation; for example @code{loc}@w{ } Intel: Square brackets; for example @code{[loc]}@w{ } @@ -27929,7 +27971,7 @@ Intel: Square brackets; for example @code{[loc]}@w{ } @display -@emph{Register contents}@w{ } +`Register contents'@w{ } @display gcc / @code{as}: Parentheses; for example @code{(%eax)}@w{ } Intel: Square brackets; for example @code{[eax]}@w{ } @@ -27940,7 +27982,7 @@ Intel: Square brackets; for example @code{[eax]}@w{ } @display -@emph{Hexadecimal numbers}@w{ } +`Hexadecimal numbers'@w{ } @display gcc / @code{as}: Leading ‘0x’ (C language syntax); for example @code{0xA0}@w{ } Intel: Trailing ‘h’; for example @code{A0h}@w{ } @@ -27951,7 +27993,7 @@ Intel: Trailing ‘h’; for example @code{A0h}@w{ } @display -@emph{Operand size}@w{ } +`Operand size'@w{ } @display gcc / @code{as}: Explicit in op code; for example @code{movw} to move a 16-bit word@w{ } Intel: Implicit, deduced by assembler; for example @code{mov}@w{ } @@ -27962,7 +28004,7 @@ Intel: Implicit, deduced by assembler; for example @code{mov}@w{ } @display -@emph{Instruction repetition}@w{ } +`Instruction repetition'@w{ } @display gcc / @code{as}: Split into two lines; for example@w{ } @display @@ -27977,7 +28019,7 @@ Intel: Keep on one line; for example @code{rep stosl}@w{ } @display -@emph{Order of operands}@w{ } +`Order of operands'@w{ } @display gcc / @code{as}: Source first; for example @code{movw $4, %eax}@w{ } Intel: Destination first; for example @code{mov eax, 4}@w{ } @@ -28008,7 +28050,7 @@ end Nothing; @end quotation @code{Asm} is a procedure declared in package @code{System.Machine_Code}; -here it takes one parameter, a @emph{template string} that must be a static +here it takes one parameter, a `template string' that must be a static expression and that will form the generated instruction. @code{Asm} may be regarded as a compile-time procedure that parses the template string and additional parameters (none here), @@ -28291,7 +28333,7 @@ most useful (for the Intel x86 processor) are the following: @multitable {xxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @item -@emph{=} +`=' @tab @@ -28299,7 +28341,7 @@ output constraint @item -@emph{g} +`g' @tab @@ -28307,7 +28349,7 @@ global (i.e., can be stored anywhere) @item -@emph{m} +`m' @tab @@ -28315,7 +28357,7 @@ in memory @item -@emph{I} +`I' @tab @@ -28323,7 +28365,7 @@ a constant @item -@emph{a} +`a' @tab @@ -28331,7 +28373,7 @@ use eax @item -@emph{b} +`b' @tab @@ -28339,7 +28381,7 @@ use ebx @item -@emph{c} +`c' @tab @@ -28347,7 +28389,7 @@ use ecx @item -@emph{d} +`d' @tab @@ -28355,7 +28397,7 @@ use edx @item -@emph{S} +`S' @tab @@ -28363,7 +28405,7 @@ use esi @item -@emph{D} +`D' @tab @@ -28371,7 +28413,7 @@ use edi @item -@emph{r} +`r' @tab @@ -28379,7 +28421,7 @@ use one of eax, ebx, ecx or edx @item -@emph{q} +`q' @tab @@ -28394,7 +28436,7 @@ documentation; note that it is possible to combine certain constraints in one constraint string. You specify the association of an output variable with an assembler operand -through the @code{%@emph{n}} notation, where @emph{n} is a non-negative +through the @code{%@var{n}} notation, where `n' is a non-negative integer. Thus in @quotation @@ -28725,7 +28767,7 @@ Asm ("movl %0, %%ebx" & LF & HT & @end quotation The Clobber parameter is a static string expression specifying the -register(s) you are using. Note that register names are @emph{not} prefixed +register(s) you are using. Note that register names are `not' prefixed by a percent sign. Also, if more than one register is used then their names are separated by commas; e.g., @code{"eax, ebx"} @@ -28790,7 +28832,7 @@ Copyright 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -@strong{Preamble} +`Preamble' The purpose of this License is to make a manual, textbook, or other functional and useful document “free†in the sense of freedom: to @@ -28813,23 +28855,23 @@ it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. -@strong{1. APPLICABILITY AND DEFINITIONS} +`1. APPLICABILITY AND DEFINITIONS' This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that -work under the conditions stated herein. The @strong{Document}, below, +work under the conditions stated herein. The `Document', below, refers to any such manual or work. Any member of the public is a -licensee, and is addressed as “@strong{you}â€. You accept the license if you +licensee, and is addressed as “`you'â€. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. -A “@strong{Modified Version}†of the Document means any work containing the +A “`Modified Version'†of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. -A “@strong{Secondary Section}†is a named appendix or a front-matter section of +A “`Secondary Section'†is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly @@ -28840,7 +28882,7 @@ connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. -The “@strong{Invariant Sections}†are certain Secondary Sections whose titles +The “`Invariant Sections'†are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not @@ -28848,12 +28890,12 @@ allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. -The “@strong{Cover Texts}†are certain short passages of text that are listed, +The “`Cover Texts'†are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. -A “@strong{Transparent}†copy of the Document means a machine-readable copy, +A “`Transparent'†copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of @@ -28864,7 +28906,7 @@ to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount -of text. A copy that is not “Transparent†is called @strong{Opaque}. +of text. A copy that is not “Transparent†is called `Opaque'. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML @@ -28877,22 +28919,22 @@ processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. -The “@strong{Title Page}†means, for a printed book, the title page itself, +The “`Title Page'†means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page†means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. -The “@strong{publisher}†means any person or entity that distributes +The “`publisher'†means any person or entity that distributes copies of the Document to the public. -A section “@strong{Entitled XYZ}†means a named subunit of the Document whose +A section “`Entitled XYZ'†means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a -specific section name mentioned below, such as “@strong{Acknowledgements}â€, -“@strong{Dedications}â€, “@strong{Endorsements}â€, or “@strong{History}â€.) -To “@strong{Preserve the Title}†+specific section name mentioned below, such as “`Acknowledgements'â€, +“`Dedications'â€, “`Endorsements'â€, or “`History'â€.) +To “`Preserve the Title'†of such a section when you modify the Document means that it remains a section “Entitled XYZ†according to this definition. @@ -28903,7 +28945,7 @@ License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. -@strong{2. VERBATIM COPYING} +`2. VERBATIM COPYING' You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the @@ -28918,7 +28960,7 @@ number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. -@strong{3. COPYING IN QUANTITY} +`3. COPYING IN QUANTITY' If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the @@ -28955,7 +28997,7 @@ It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. -@strong{4. MODIFICATIONS} +`4. MODIFICATIONS' You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release @@ -29072,7 +29114,7 @@ The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. -@strong{5. COMBINING DOCUMENTS} +`5. COMBINING DOCUMENTS' You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified @@ -29096,7 +29138,7 @@ in the various original documents, forming one section Entitled and any sections Entitled “Dedicationsâ€. You must delete all sections Entitled “Endorsementsâ€. -@strong{6. COLLECTIONS OF DOCUMENTS} +`6. COLLECTIONS OF DOCUMENTS' You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this @@ -29109,7 +29151,7 @@ it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. -@strong{7. AGGREGATION WITH INDEPENDENT WORKS} +`7. AGGREGATION WITH INDEPENDENT WORKS' A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or @@ -29128,7 +29170,7 @@ electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. -@strong{8. TRANSLATION} +`8. TRANSLATION' Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. @@ -29148,7 +29190,7 @@ If a section in the Document is Entitled “Acknowledgementsâ€, its Title (section 1) will typically require changing the actual title. -@strong{9. TERMINATION} +`9. TERMINATION' You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt @@ -29175,7 +29217,7 @@ this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. -@strong{10. FUTURE REVISIONS OF THIS LICENSE} +`10. FUTURE REVISIONS OF THIS LICENSE' The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new @@ -29196,7 +29238,7 @@ License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. -@strong{11. RELICENSING} +`11. RELICENSING' “Massive Multiauthor Collaboration Site†(or “MMC Siteâ€) means any World Wide Web server that publishes copyrightable works and also @@ -29225,7 +29267,7 @@ The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. -@strong{ADDENDUM: How to use this License for your documents} +`ADDENDUM: How to use this License for your documents' To use this License in a document you have written, include a copy of the License in the document and put the following copyright and @@ -29266,8 +29308,8 @@ to permit their use in free software. @printindex ge -@anchor{cf}@w{ } @anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } +@anchor{cf}@w{ } @c %**end of body @bye diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb index b6cdee0..e4187dd 100644 --- a/gcc/ada/layout.adb +++ b/gcc/ada/layout.adb @@ -1053,8 +1053,6 @@ package body Layout is -- derived types. declare - FST : constant Entity_Id := First_Subtype (E); - function Has_Attribute_Clause (E : Entity_Id; Id : Attribute_Id) return Boolean; @@ -1072,7 +1070,17 @@ package body Layout is return Present (Get_Attribute_Definition_Clause (E, Id)); end Has_Attribute_Clause; + FST : Entity_Id; + begin + FST := First_Subtype (E); + + -- Deal with private types + + if Is_Private_Type (FST) then + FST := Full_View (FST); + end if; + -- If the alignment comes from a clause, then we respect it. -- Consider for example: diff --git a/gcc/ada/libgnat/a-coinve.adb b/gcc/ada/libgnat/a-coinve.adb index c84175a..46d6730 100644 --- a/gcc/ada/libgnat/a-coinve.adb +++ b/gcc/ada/libgnat/a-coinve.adb @@ -197,12 +197,29 @@ is Count : Count_Type) is begin - -- In the general case, we pass the buck to Insert, but for efficiency, - -- we check for the usual case where Count = 1 and the vector has enough - -- room for at least one more element. + -- In the general case, we take the slow path; for efficiency, + -- we check for the common case where Count = 1 . - if Count = 1 - and then Container.Elements /= null + if Count = 1 then + Append (Container, New_Item); + else + Append_Slow_Path (Container, New_Item, Count); + end if; + end Append; + + ------------ + -- Append -- + ------------ + + procedure Append (Container : in out Vector; + New_Item : Element_Type) + is + begin + -- For performance, check for the common special case where the + -- container already has room for at least one more element. + -- In the general case, pass the buck to Insert. + + if Container.Elements /= null and then Container.Last /= Container.Elements.Last then TC_Check (Container.TC); @@ -223,23 +240,11 @@ is Container.Elements.EA (New_Last) := new Element_Type'(New_Item); Container.Last := New_Last; end; - else - Append_Slow_Path (Container, New_Item, Count); + Insert (Container, Last_Index (Container) + 1, New_Item, 1); end if; end Append; - ------------ - -- Append -- - ------------ - - procedure Append (Container : in out Vector; - New_Item : Element_Type) - is - begin - Insert (Container, Last_Index (Container) + 1, New_Item, 1); - end Append; - ---------------------- -- Append_Slow_Path -- ---------------------- diff --git a/gcc/ada/libgnat/a-convec.adb b/gcc/ada/libgnat/a-convec.adb index 3a2adae..751d468 100644 --- a/gcc/ada/libgnat/a-convec.adb +++ b/gcc/ada/libgnat/a-convec.adb @@ -173,27 +173,11 @@ is Count : Count_Type) is begin - -- In the general case, we pass the buck to Insert, but for efficiency, - -- we check for the usual case where Count = 1 and the vector has enough - -- room for at least one more element. - - if Count = 1 - and then Container.Elements /= null - and then Container.Last /= Container.Elements.Last - then - TC_Check (Container.TC); - - -- Increment Container.Last after assigning the New_Item, so we - -- leave the Container unmodified in case Finalize/Adjust raises - -- an exception. - - declare - New_Last : constant Index_Type := Container.Last + 1; - begin - Container.Elements.EA (New_Last) := New_Item; - Container.Last := New_Last; - end; + -- In the general case, we take the slow path; for efficiency, + -- we check for the common case where Count = 1 . + if Count = 1 then + Append (Container, New_Item); else Append_Slow_Path (Container, New_Item, Count); end if; @@ -222,7 +206,28 @@ is New_Item : Element_Type) is begin - Insert (Container, Last_Index (Container) + 1, New_Item, 1); + -- For performance, check for the common special case where the + -- container already has room for at least one more element. + -- In the general case, pass the buck to Insert. + + if Container.Elements /= null + and then Container.Last /= Container.Elements.Last + then + TC_Check (Container.TC); + + -- Increment Container.Last after assigning the New_Item, so we + -- leave the Container unmodified in case Finalize/Adjust raises + -- an exception. + + declare + New_Last : constant Index_Type := Container.Last + 1; + begin + Container.Elements.EA (New_Last) := New_Item; + Container.Last := New_Last; + end; + else + Insert (Container, Last_Index (Container) + 1, New_Item, 1); + end if; end Append; ---------------------- diff --git a/gcc/ada/libgnat/a-nbnbig.ads b/gcc/ada/libgnat/a-nbnbig.ads index f574e78..3979f14 100644 --- a/gcc/ada/libgnat/a-nbnbig.ads +++ b/gcc/ada/libgnat/a-nbnbig.ads @@ -32,6 +32,8 @@ package Ada.Numerics.Big_Numbers.Big_Integers_Ghost with Ghost, Pure is + pragma Annotate (GNATprove, Always_Return, Big_Integers_Ghost); + type Big_Integer is private with Integer_Literal => From_Universal_Image; diff --git a/gcc/ada/libgnat/a-strmap.adb b/gcc/ada/libgnat/a-strmap.adb index 77780f9..e092db0 100644 --- a/gcc/ada/libgnat/a-strmap.adb +++ b/gcc/ada/libgnat/a-strmap.adb @@ -290,6 +290,7 @@ is loop pragma Loop_Invariant (Seq1 (Seq1'First .. J) = Seq2 (Seq2'First .. J)); + pragma Loop_Variant (Increases => J); if J = Positive'Last then return; @@ -440,6 +441,7 @@ is (Character'Pos (C) >= Character'Pos (C'Loop_Entry)); pragma Loop_Invariant (for all Char in C'Loop_Entry .. C => not Set (Char)); + pragma Loop_Variant (Increases => C); exit when C = Character'Last; C := Character'Succ (C); end loop; @@ -457,6 +459,7 @@ is pragma Loop_Invariant (for all Char in C'Loop_Entry .. C => (if Char /= C then Set (Char))); + pragma Loop_Variant (Increases => C); exit when not Set (C) or else C = Character'Last; C := Character'Succ (C); end loop; @@ -491,6 +494,7 @@ is pragma Loop_Invariant (for all Span of Max_Ranges (1 .. Range_Num) => (for all Char in Span.Low .. Span.High => Set (Char))); + pragma Loop_Variant (Increases => Range_Num); end loop; return Max_Ranges (1 .. Range_Num); diff --git a/gcc/ada/libgnat/a-strsea.adb b/gcc/ada/libgnat/a-strsea.adb index 71a415f..652c797 100644 --- a/gcc/ada/libgnat/a-strsea.adb +++ b/gcc/ada/libgnat/a-strsea.adb @@ -113,6 +113,7 @@ package body Ada.Strings.Search with SPARK_Mode is pragma Loop_Invariant (Num <= Ind - (Source'First - 1)); pragma Loop_Invariant (Ind >= Source'First); + pragma Loop_Variant (Increases => Ind); end loop; -- Mapped case @@ -142,6 +143,7 @@ package body Ada.Strings.Search with SPARK_Mode is null; pragma Loop_Invariant (Num <= Ind - (Source'First - 1)); pragma Loop_Invariant (Ind >= Source'First); + pragma Loop_Variant (Increases => Ind); end loop; end if; @@ -200,6 +202,7 @@ package body Ada.Strings.Search with SPARK_Mode is null; pragma Loop_Invariant (Num <= Ind - (Source'First - 1)); pragma Loop_Invariant (Ind >= Source'First); + pragma Loop_Variant (Increases => Ind); end loop; return Num; diff --git a/gcc/ada/libgnat/s-aridou.adb b/gcc/ada/libgnat/s-aridou.adb index b40e4c3..52f2360 100644 --- a/gcc/ada/libgnat/s-aridou.adb +++ b/gcc/ada/libgnat/s-aridou.adb @@ -126,7 +126,7 @@ is Pre => B /= 0; -- Length doubling remainder - function Big_2xx (N : Natural) return Big_Integer is + function Big_2xx (N : Natural) return Big_Positive is (Big (Double_Uns'(2 ** N))) with Ghost, @@ -141,6 +141,13 @@ is with Ghost; -- X1&X2&X3 as a big integer + function Big3 (X1, X2, X3 : Big_Integer) return Big_Integer is + (Big_2xxSingle * Big_2xxSingle * X1 + + Big_2xxSingle * X2 + + X3) + with Ghost; + -- Version of Big3 on big integers + function Le3 (X1, X2, X3, Y1, Y2, Y3 : Single_Uns) return Boolean with Post => Le3'Result = (Big3 (X1, X2, X3) <= Big3 (Y1, Y2, Y3)); @@ -234,6 +241,17 @@ is Pre => X /= Double_Uns'Last, Post => Big (X + Double_Uns'(1)) = Big (X) + 1; + procedure Lemma_Big_Of_Double_Uns (X : Double_Uns) + with + Ghost, + Post => Big (X) < Big_2xxDouble; + + procedure Lemma_Big_Of_Double_Uns_Of_Single_Uns (X : Single_Uns) + with + Ghost, + Post => Big (Double_Uns (X)) >= 0 + and then Big (Double_Uns (X)) < Big_2xxSingle; + procedure Lemma_Bounded_Powers_Of_2_Increasing (M, N : Natural) with Ghost, @@ -447,9 +465,9 @@ is procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer) with Ghost, - Pre => (X >= Big_0 and then Y >= Big_0) - or else (X <= Big_0 and then Y <= Big_0), - Post => X * Y >= Big_0; + Pre => (X >= 0 and then Y >= 0) + or else (X <= 0 and then Y <= 0), + Post => X * Y >= 0; procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer) with @@ -458,6 +476,13 @@ is or else (X >= Big_0 and then Y <= Big_0), Post => X * Y <= Big_0; + procedure Lemma_Mult_Positive (X, Y : Big_Integer) + with + Ghost, + Pre => (X > Big_0 and then Y > Big_0) + or else (X < Big_0 and then Y < Big_0), + Post => X * Y > Big_0; + procedure Lemma_Neg_Div (X, Y : Big_Integer) with Ghost, @@ -604,6 +629,8 @@ is procedure Lemma_Abs_Range (X : Big_Integer) is null; procedure Lemma_Add_Commutation (X : Double_Uns; Y : Single_Uns) is null; procedure Lemma_Add_One (X : Double_Uns) is null; + procedure Lemma_Big_Of_Double_Uns (X : Double_Uns) is null; + procedure Lemma_Big_Of_Double_Uns_Of_Single_Uns (X : Single_Uns) is null; procedure Lemma_Bounded_Powers_Of_2_Increasing (M, N : Natural) is null; procedure Lemma_Deep_Mult_Commutation (Factor : Big_Integer; @@ -638,6 +665,7 @@ is procedure Lemma_Mult_Distribution (X, Y, Z : Big_Integer) is null; procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer) is null; procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer) is null; + procedure Lemma_Mult_Positive (X, Y : Big_Integer) is null; procedure Lemma_Neg_Rem (X, Y : Big_Integer) is null; procedure Lemma_Not_In_Range_Big2xx64 is null; procedure Lemma_Powers (A : Big_Natural; B, C : Natural) is null; @@ -1888,7 +1916,7 @@ is -- Local ghost variables - Mult : constant Big_Integer := abs (Big (X) * Big (Y)) with Ghost; + Mult : constant Big_Natural := abs (Big (X) * Big (Y)) with Ghost; Quot : Big_Integer with Ghost; Big_R : Big_Integer with Ghost; Big_Q : Big_Integer with Ghost; @@ -1955,6 +1983,15 @@ is -- Proves correctness of the multiplication of divisor by quotient to -- compute amount to subtract. + procedure Prove_Mult_Decomposition_Split3 + (D1, D2, D3, D3_Hi, D3_Lo, D4 : Big_Integer) + with + Ghost, + Pre => Is_Mult_Decomposition (D1, D2, D3, D4) + and then D3 = Big_2xxSingle * D3_Hi + D3_Lo, + Post => Is_Mult_Decomposition (D1, D2 + D3_Hi, D3_Lo, D4); + -- Proves decomposition of Mult after splitting third component + procedure Prove_Negative_Dividend with Ghost, @@ -2066,6 +2103,27 @@ is else abs Quot); -- Proves correctness of the rounding of the unsigned quotient + procedure Prove_Scaled_Mult_Decomposition_Regroup24 + (D1, D2, D3, D4 : Big_Integer) + with + Ghost, + Pre => Scale < Double_Size + and then Is_Scaled_Mult_Decomposition (D1, D2, D3, D4), + Post => Is_Scaled_Mult_Decomposition + (0, Big_2xxSingle * D1 + D2, 0, Big_2xxSingle * D3 + D4); + -- Proves scaled decomposition of Mult after regrouping on second and + -- fourth component. + + procedure Prove_Scaled_Mult_Decomposition_Regroup3 + (D1, D2, D3, D4 : Big_Integer) + with + Ghost, + Pre => Scale < Double_Size + and then Is_Scaled_Mult_Decomposition (D1, D2, D3, D4), + Post => Is_Scaled_Mult_Decomposition (0, 0, Big3 (D1, D2, D3), D4); + -- Proves scaled decomposition of Mult after regrouping on third + -- component. + procedure Prove_Sign_R with Ghost, @@ -2315,6 +2373,14 @@ is + Big (Double_Uns (S3)))); end Prove_Multiplication; + ------------------------------------- + -- Prove_Mult_Decomposition_Split3 -- + ------------------------------------- + + procedure Prove_Mult_Decomposition_Split3 + (D1, D2, D3, D3_Hi, D3_Lo, D4 : Big_Integer) + is null; + ----------------------------- -- Prove_Negative_Dividend -- ----------------------------- @@ -2413,6 +2479,22 @@ is end if; end Prove_Rounding_Case; + ----------------------------------------------- + -- Prove_Scaled_Mult_Decomposition_Regroup24 -- + ----------------------------------------------- + + procedure Prove_Scaled_Mult_Decomposition_Regroup24 + (D1, D2, D3, D4 : Big_Integer) + is null; + + ---------------------------------------------- + -- Prove_Scaled_Mult_Decomposition_Regroup3 -- + ---------------------------------------------- + + procedure Prove_Scaled_Mult_Decomposition_Regroup3 + (D1, D2, D3, D4 : Big_Integer) + is null; + ------------------ -- Prove_Sign_R -- ------------------ @@ -2585,29 +2667,15 @@ is T2 := D (3) + Lo (T1); Lemma_Add_Commutation (Double_Uns (D (3)), Lo (T1)); - pragma Assert - (Is_Mult_Decomposition - (D1 => 0, - D2 => Big (Double_Uns'(Xhi * Yhi)) + Big (Double_Uns (D (2))) - + Big (Double_Uns (Hi (T1))), - D3 => Big (T2), - D4 => Big (Double_Uns (D (4))))); Lemma_Hi_Lo (T2, Hi (T2), Lo (T2)); - pragma Assert - (By (Is_Mult_Decomposition - (D1 => 0, - D2 => Big (Double_Uns'(Xhi * Yhi)) + Big (Double_Uns (D (2))) - + Big (Double_Uns (Hi (T1))) + Big (Double_Uns (Hi (T2))), - D3 => Big (Double_Uns (Lo (T2))), - D4 => Big (Double_Uns (D (4)))), - By (Big_2xxSingle * Big (T2) = - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2))) - + Big_2xxSingle * Big (Double_Uns (Lo (T2))), - Big_2xxSingle * - (Big_2xxSingle * Big (Double_Uns (Hi (T2))) - + Big (Double_Uns (Lo (T2)))) - = Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2))) - + Big_2xxSingle * Big (Double_Uns (Lo (T2)))))); + Prove_Mult_Decomposition_Split3 + (D1 => 0, + D2 => Big (Double_Uns'(Xhi * Yhi)) + Big (Double_Uns (D (2))) + + Big (Double_Uns (Hi (T1))), + D3 => Big (T2), + D3_Hi => Big (Double_Uns (Hi (T2))), + D3_Lo => Big (Double_Uns (Lo (T2))), + D4 => Big (Double_Uns (D (4)))); D (3) := Lo (T2); T3 := D (2) + Hi (T1); @@ -2807,8 +2875,20 @@ is pragma Assert (Mult >= Big_2xxSingle * Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1)))); + Lemma_Double_Big_2xxSingle; + Lemma_Mult_Positive (Big_2xxDouble, Big_2xxSingle); + Lemma_Ge_Mult (Big (Double_Uns (D (1))), + 1, + Big_2xxDouble * Big_2xxSingle, + Big_2xxDouble * Big_2xxSingle); + Lemma_Mult_Positive (Big_2xxSingle, Big (Double_Uns (D (1)))); + Lemma_Ge_Mult (Big_2xxSingle * Big_2xxSingle, Big_2xxDouble, + Big_2xxSingle * Big (Double_Uns (D (1))), + Big_2xxDouble * Big_2xxSingle); pragma Assert (Mult >= Big_2xxDouble * Big_2xxSingle); Lemma_Ge_Commutation (2 ** Single_Size, Zu); + Lemma_Ge_Mult (Big_2xxSingle, Big (Zu), Big_2xxDouble, + Big_2xxDouble * Big (Zu)); pragma Assert (Mult >= Big_2xxDouble * Big (Zu)); else Lemma_Ge_Commutation (Double_Uns (D (2)), Zu); @@ -2887,6 +2967,13 @@ is Post => Shift / 2 = 2 ** (Log_Single_Size - (Inter + 1)) and then (Shift = 2 or (Shift / 2) mod 2 = 0); + procedure Prove_Prev_And_Mask (Prev, Mask : Single_Uns) + with + Ghost, + Pre => Prev /= 0 + and then (Prev and Mask) = 0, + Post => (Prev and not Mask) /= 0; + procedure Prove_Shift_Progress with Ghost, @@ -2918,6 +3005,7 @@ is -- Local lemma null bodies -- ----------------------------- + procedure Prove_Prev_And_Mask (Prev, Mask : Single_Uns) is null; procedure Prove_Power is null; procedure Prove_Shifting is null; procedure Prove_Shift_Progress is null; @@ -2941,6 +3029,15 @@ is if (Hi (Zu) and Mask) = 0 then Zu := Shift_Left (Zu, Shift); + pragma Assert ((Hi (Zu_Prev) and Mask_Prev) /= 0); + pragma Assert + (By ((Hi (Zu_Prev) and Mask_Prev and Mask) = 0, + (Hi (Zu_Prev) and Mask) = 0 + and then + (Hi (Zu_Prev) and Mask_Prev and Mask) + = (Hi (Zu_Prev) and Mask and Mask_Prev) + )); + Prove_Prev_And_Mask (Hi (Zu_Prev) and Mask_Prev, Mask); Prove_Shifting; pragma Assert (Big (Zu_Prev) = Big (Double_Uns'(abs Z)) * Big_2xx (Scale)); @@ -2986,6 +3083,7 @@ is -- not change the invariant that (D (1) & D (2)) < Zu. Lemma_Lt_Commutation (D (1) & D (2), abs Z); + Lemma_Big_Of_Double_Uns (Zu); Lemma_Lt_Mult (Big (D (1) & D (2)), Big (Double_Uns'(abs Z)), Big_2xx (Scale), Big_2xxDouble); @@ -3007,82 +3105,21 @@ is * Big (Double_Uns (Hi (T1))) = Big_2xxSingle * Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1)))); - - pragma Assert - (Is_Scaled_Mult_Decomposition - (Big (Double_Uns (D (1))), - Big (Double_Uns (D (2))), - Big (Double_Uns (D (3))), - Big (Double_Uns (D (4))))); - pragma Assert - (By (Is_Scaled_Mult_Decomposition - (0, - 0, - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big (Double_Uns (D (2))) - + Big (Double_Uns (D (3))), - Big (Double_Uns (D (4)))), - Big_2xxSingle * - (Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big (Double_Uns (D (2))) - + Big (Double_Uns (D (3)))) - + Big (Double_Uns (D (4))) = - Big_2xxSingle * - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (2))) - + Big_2xxSingle * Big (Double_Uns (D (3))) - + Big (Double_Uns (D (4))) - and then - (By (Mult * Big_2xx (Scale) = - Big_2xxSingle * - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (2))) - + Big_2xxSingle * Big (Double_Uns (D (3))) - + Big (Double_Uns (D (4))), - Is_Scaled_Mult_Decomposition - (Big (Double_Uns (D (1))), - Big (Double_Uns (D (2))), - Big (Double_Uns (D (3))), - Big (Double_Uns (D (4)))))))); - Lemma_Substitution - (Mult * Big_2xx (Scale), Big_2xxSingle, - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big (Double_Uns (D (2))) - + Big (Double_Uns (D (3))), - Big3 (D (1), D (2), D (3)), - Big (Double_Uns (D (4)))); Lemma_Substitution (Big_2xxDouble * Big (Zu), Big_2xxDouble, Big (Zu), Big (Double_Uns'(abs Z)) * Big_2xx (Scale), 0); Lemma_Lt_Mult (Mult, Big_2xxDouble * Big (Double_Uns'(abs Z)), Big_2xx (Scale), Big_2xxDouble * Big (Zu)); + pragma Assert (Mult >= Big_0); + pragma Assert (Big_2xx (Scale) >= Big_0); + Lemma_Mult_Non_Negative (Mult, Big_2xx (Scale)); Lemma_Div_Lt (Mult * Big_2xx (Scale), Big (Zu), Big_2xxDouble); Lemma_Concat_Definition (D (1), D (2)); Lemma_Double_Big_2xxSingle; - pragma Assert - (Big_2xxSingle * - (Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big (Double_Uns (D (2))) - + Big (Double_Uns (D (3)))) - + Big (Double_Uns (D (4))) - = Big_2xxSingle * Big_2xxSingle * - (Big_2xxSingle * Big (Double_Uns (D (1))) - + Big (Double_Uns (D (2)))) - + Big_2xxSingle * Big (Double_Uns (D (3))) - + Big (Double_Uns (D (4)))); - pragma Assert - (By (Is_Scaled_Mult_Decomposition - (0, - Big_2xxSingle * Big (Double_Uns (D (1))) - + Big (Double_Uns (D (2))), - 0, - Big_2xxSingle * Big (Double_Uns (D (3))) - + Big (Double_Uns (D (4)))), - Big_2xxSingle * Big_2xxSingle * - (Big_2xxSingle * Big (Double_Uns (D (1))) - + Big (Double_Uns (D (2)))) = - Big_2xxSingle * - Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (1))) - + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (2))))); + Prove_Scaled_Mult_Decomposition_Regroup24 + (Big (Double_Uns (D (1))), + Big (Double_Uns (D (2))), + Big (Double_Uns (D (3))), + Big (Double_Uns (D (4)))); Lemma_Substitution (Mult * Big_2xx (Scale), Big_2xxSingle * Big_2xxSingle, Big_2xxSingle * Big (Double_Uns (D (1))) @@ -3115,10 +3152,20 @@ is -- Local ghost variables Qd1 : Single_Uns := 0 with Ghost; + D234 : Big_Integer := 0 with Ghost; D123 : constant Big_Integer := Big3 (D (1), D (2), D (3)) with Ghost; + D4 : constant Big_Integer := Big (Double_Uns (D (4))) + with Ghost; begin + Prove_Scaled_Mult_Decomposition_Regroup3 + (Big (Double_Uns (D (1))), + Big (Double_Uns (D (2))), + Big (Double_Uns (D (3))), + Big (Double_Uns (D (4)))); + pragma Assert (Mult * Big_2xx (Scale) = Big_2xxSingle * D123 + D4); + for J in 1 .. 2 loop Lemma_Hi_Lo (D (J) & D (J + 1), D (J), D (J + 1)); pragma Assert (Big (D (J) & D (J + 1)) < Big (Zu)); @@ -3138,6 +3185,7 @@ is Qd (J) := Single_Uns'Last; Lemma_Concat_Definition (D (J), D (J + 1)); + Lemma_Big_Of_Double_Uns_Of_Single_Uns (D (J + 2)); pragma Assert (Big_2xxSingle > Big (Double_Uns (D (J + 2)))); pragma Assert (Big3 (D (J), D (J + 1), 0) + Big_2xxSingle > Big3 (D (J), D (J + 1), D (J + 2))); @@ -3158,6 +3206,8 @@ is Lemma_Div_Lt (Big3 (D (J), D (J + 1), D (J + 2)), Big_2xxSingle, Big (Zu)); + pragma Assert (Big (Double_Uns (Qd (J))) >= + Big3 (D (J), D (J + 1), D (J + 2)) / Big (Zu)); else Qd (J) := Lo ((D (J) & D (J + 1)) / Zhi); @@ -3165,6 +3215,7 @@ is Prove_Qd_Calculation_Part_1 (J); end if; + pragma Assert (for all K in 1 .. J => Qd (K)'Initialized); Lemma_Gt_Mult (Big (Double_Uns (Qd (J))), Big3 (D (J), D (J + 1), D (J + 2)) / Big (Zu), @@ -3199,7 +3250,9 @@ is Lemma_Hi_Lo_3 (Zu, Zhi, Zlo); while not Le3 (S1, S2, S3, D (J), D (J + 1), D (J + 2)) loop - pragma Loop_Invariant (Qd (J)'Initialized); + pragma Loop_Invariant + (for all K in 1 .. J => Qd (K)'Initialized); + pragma Loop_Invariant (if J = 2 then Qd (1) = Qd1); pragma Loop_Invariant (Big3 (S1, S2, S3) = Big (Double_Uns (Qd (J))) * Big (Zu)); pragma Loop_Invariant @@ -3240,6 +3293,7 @@ is -- Now subtract S1&S2&S3 from D1&D2&D3 ready for next step + pragma Assert (for all K in 1 .. J => Qd (K)'Initialized); pragma Assert (Big3 (S1, S2, S3) = Big (Double_Uns (Qd (J))) * Big (Zu)); pragma Assert (Big3 (S1, S2, S3) > @@ -3256,19 +3310,32 @@ is * Big_2xxSingle * Big (Double_Uns (D (J))) + Big_2xxSingle * Big (Double_Uns (D (J + 1))) + Big (Double_Uns (D (J + 2)))); - pragma Assert (Big3 (D (J), D (J + 1), D (J + 2)) = - Big_2xxDouble * Big (Double_Uns (D (J))) - + Big_2xxSingle * Big (Double_Uns (D (J + 1))) - + Big (Double_Uns (D (J + 2)))); pragma Assert (Big_2xxSingle >= 0); + Lemma_Big_Of_Double_Uns_Of_Single_Uns (D (J + 1)); pragma Assert (Big (Double_Uns (D (J + 1))) >= 0); + Lemma_Mult_Non_Negative + (Big_2xxSingle, Big (Double_Uns (D (J + 1)))); pragma Assert - (Big_2xxSingle * Big (Double_Uns (D (J + 1))) >= 0); - pragma Assert - (Big_2xxSingle * Big (Double_Uns (D (J + 1))) - + Big (Double_Uns (D (J + 2))) >= 0); - pragma Assert (Big3 (D (J), D (J + 1), D (J + 2)) >= - Big_2xxDouble * Big (Double_Uns (D (J)))); + (By (Big3 (D (J), D (J + 1), D (J + 2)) >= + Big_2xxSingle * Big_2xxSingle + * Big (Double_Uns (D (J))), + By (Big3 (D (J), D (J + 1), D (J + 2)) + - Big_2xxSingle * Big_2xxSingle + * Big (Double_Uns (D (J))) + = Big_2xxSingle * Big (Double_Uns (D (J + 1))) + + Big (Double_Uns (D (J + 2))), + Big3 (D (J), D (J + 1), D (J + 2)) = + Big_2xxSingle + * Big_2xxSingle * Big (Double_Uns (D (J))) + + Big_2xxSingle * Big (Double_Uns (D (J + 1))) + + Big (Double_Uns (D (J + 2)))) + and then + By (Big_2xxSingle * Big (Double_Uns (D (J + 1))) + + Big (Double_Uns (D (J + 2))) >= 0, + Big_2xxSingle * Big (Double_Uns (D (J + 1))) >= 0 + and then + Big (Double_Uns (D (J + 2))) >= 0 + ))); Lemma_Ge_Commutation (Double_Uns (D (J)), Double_Uns'(1)); Lemma_Ge_Mult (Big (Double_Uns (D (J))), Big (Double_Uns'(1)), @@ -3283,6 +3350,8 @@ is if J = 1 then Qd1 := Qd (1); + D234 := Big3 (D (2), D (3), D (4)); + pragma Assert (D4 = Big (Double_Uns (D (4)))); Lemma_Substitution (Mult * Big_2xx (Scale), Big_2xxSingle, D123, Big3 (D (1), D (2), D (3)) + Big3 (S1, S2, S3), @@ -3291,23 +3360,38 @@ is Lemma_Substitution (Mult * Big_2xx (Scale), Big_2xxSingle, Big3 (S1, S2, S3), Big (Double_Uns (Qd1)) * Big (Zu), - Big3 (D (2), D (3), D (4))); + D234); else pragma Assert (Qd1 = Qd (1)); pragma Assert - (Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (2))) - = 0); - pragma Assert - (Mult * Big_2xx (Scale) = - Big_2xxSingle * Big (Double_Uns (Qd (1))) * Big (Zu) + (By (Mult * Big_2xx (Scale) = + Big_2xxSingle * Big (Double_Uns (Qd1)) * Big (Zu) + Big3 (S1, S2, S3) - + Big3 (D (2), D (3), D (4))); + + Big3 (D (2), D (3), D (4)), + Big3 (D (2), D (3), D (4)) = D234 - Big3 (S1, S2, S3))); pragma Assert - (Mult * Big_2xx (Scale) = + (By (Mult * Big_2xx (Scale) = Big_2xxSingle * Big (Double_Uns (Qd (1))) * Big (Zu) + Big (Double_Uns (Qd (2))) * Big (Zu) + Big_2xxSingle * Big (Double_Uns (D (3))) - + Big (Double_Uns (D (4)))); + + Big (Double_Uns (D (4))), + Big_2xxSingle * Big (Double_Uns (Qd (1))) * Big (Zu) + = Big_2xxSingle * Big (Double_Uns (Qd1)) * Big (Zu) + and then + Big3 (S1, S2, S3) = Big (Double_Uns (Qd (2))) * Big (Zu) + and then + By (Big3 (D (2), D (3), D (4)) + = Big_2xxSingle * Big (Double_Uns (D (3))) + + Big (Double_Uns (D (4))), + Big3 (D (2), D (3), D (4)) + = Big_2xxSingle * Big_2xxSingle * + Big (Double_Uns (D (2))) + + Big_2xxSingle * Big (Double_Uns (D (3))) + + Big (Double_Uns (D (4))) + and then + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (D (2))) + = 0) + )); end if; end loop; end; @@ -3319,6 +3403,7 @@ is -- We rescale the divisor as well, to make the proper comparison -- for rounding below. + pragma Assert (for all K in 1 .. 2 => Qd (K)'Initialized); Qu := Qd (1) & Qd (2); Ru := D (3) & D (4); @@ -3440,14 +3525,14 @@ is Ghost, Pre => X2 < Y2, Post => Big3 (X1, X2 - Y2, X3) - = Big3 (X1, X2, X3) + Big3 (1, 0, 0) - Big3 (0, Y2, 0); + = Big3 (X1, X2, X3) + Big3 (Single_Uns'(1), 0, 0) - Big3 (0, Y2, 0); procedure Lemma_Sub3_With_Carry3 (X1, X2, X3, Y3 : Single_Uns) with Ghost, Pre => X3 < Y3, Post => Big3 (X1, X2, X3 - Y3) - = Big3 (X1, X2, X3) + Big3 (0, 1, 0) - Big3 (0, 0, Y3); + = Big3 (X1, X2, X3) + Big3 (Single_Uns'(0), 1, 0) - Big3 (0, 0, Y3); ------------------------- -- Lemma_Add3_No_Carry -- @@ -3522,10 +3607,12 @@ is X1 := X1 - 1; pragma Assert - (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - Big3 (1, 0, 0)); + (Big3 (X1, X2, X3) = + Big3 (XX1, XX2, XX3) - Big3 (Single_Uns'(1), 0, 0)); pragma Assert (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - - Big3 (0, Single_Uns'Last, 0) - Big3 (0, 1, 0)); + - Big3 (Single_Uns'(0), Single_Uns'Last, 0) + - Big3 (Single_Uns'(0), 1, 0)); Lemma_Add3_No_Carry (X1, X2, X3, 0, Single_Uns'Last, 0); else Lemma_Sub3_No_Carry (X1, X2, X3, 0, 1, 0); @@ -3534,7 +3621,8 @@ is X2 := X2 - 1; pragma Assert - (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - Big3 (0, 1, 0)); + (Big3 (X1, X2, X3) = + Big3 (XX1, XX2, XX3) - Big3 (Single_Uns'(0), 1, 0)); Lemma_Sub3_With_Carry3 (X1, X2, X3, Y3); else Lemma_Sub3_No_Carry (X1, X2, X3, 0, 0, Y3); @@ -3553,7 +3641,7 @@ is pragma Assert (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - - Big3 (0, 0, Y3) - Big3 (1, 0, 0)); + - Big3 (0, 0, Y3) - Big3 (Single_Uns'(1), 0, 0)); Lemma_Sub3_With_Carry2 (X1, X2, X3, Y2); else Lemma_Sub3_No_Carry (X1, X2, X3, 0, Y2, 0); diff --git a/gcc/ada/libgnat/s-aridou.ads b/gcc/ada/libgnat/s-aridou.ads index 29e13a5..08af4f5 100644 --- a/gcc/ada/libgnat/s-aridou.ads +++ b/gcc/ada/libgnat/s-aridou.ads @@ -69,6 +69,7 @@ is package BI_Ghost renames Ada.Numerics.Big_Numbers.Big_Integers_Ghost; subtype Big_Integer is BI_Ghost.Big_Integer with Ghost; subtype Big_Natural is BI_Ghost.Big_Natural with Ghost; + subtype Big_Positive is BI_Ghost.Big_Positive with Ghost; use type BI_Ghost.Big_Integer; package Signed_Conversion is diff --git a/gcc/ada/libgnat/s-expmod.adb b/gcc/ada/libgnat/s-expmod.adb index 527338d..f1fdf71 100644 --- a/gcc/ada/libgnat/s-expmod.adb +++ b/gcc/ada/libgnat/s-expmod.adb @@ -106,6 +106,13 @@ is ------------------- procedure Lemma_Add_Mod (X, Y : Big_Natural; B : Big_Positive) is + + procedure Lemma_Euclidean_Mod (Q, F, R : Big_Natural) with + Pre => F /= 0, + Post => (Q * F + R) mod F = R mod F; + + procedure Lemma_Euclidean_Mod (Q, F, R : Big_Natural) is null; + Left : constant Big_Natural := (X + Y) mod B; Right : constant Big_Natural := ((X mod B) + (Y mod B)) mod B; XQuot : constant Big_Natural := X / B; @@ -119,6 +126,8 @@ is (Left = ((XQuot + YQuot) * B + X mod B + Y mod B) mod B); pragma Assert (X mod B + Y mod B = AQuot * B + Right); pragma Assert (Left = ((XQuot + YQuot + AQuot) * B + Right) mod B); + Lemma_Euclidean_Mod (XQuot + YQuot + AQuot, B, Right); + pragma Assert (Left = (Right mod B)); pragma Assert (Left = Right); end if; end Lemma_Add_Mod; @@ -259,6 +268,7 @@ is pragma Assert (Equal_Modulo ((Big (Result) * Big (Factor)) * Big (Factor) ** (Exp - 1), Big (Left) ** Right)); + pragma Assert (Big (Factor) >= 0); Lemma_Mult_Mod (Big (Result) * Big (Factor), Big (Factor) ** (Exp - 1), Big (Modulus)); diff --git a/gcc/ada/libgnat/s-imagef.adb b/gcc/ada/libgnat/s-imagef.adb index fd8e848..bfe8540 100644 --- a/gcc/ada/libgnat/s-imagef.adb +++ b/gcc/ada/libgnat/s-imagef.adb @@ -31,7 +31,8 @@ with System.Image_I; with System.Img_Util; use System.Img_Util; -with System.Val_Util; +with System.Value_I_Spec; +with System.Value_U_Spec; package body System.Image_F is @@ -69,70 +70,16 @@ package body System.Image_F is -- if the small is larger than 1, and smaller than 2**(Int'Size - 1) / 10 -- if the small is smaller than 1. - -- Define ghost subprograms without implementation (marked as Import) to - -- create a suitable package Int_Params for type Int, as instantiations - -- of System.Image_F use for this type one of the derived integer types - -- defined in Interfaces, instead of the standard signed integer types - -- which are used to define System.Img_*.Int_Params. - - type Uns_Option (Overflow : Boolean := False) is record - case Overflow is - when True => - null; - when False => - Value : Uns := 0; - end case; - end record; - Unsigned_Width_Ghost : constant Natural := Int'Width; - function Wrap_Option (Value : Uns) return Uns_Option - with Ghost, Import; - function Only_Decimal_Ghost - (Str : String; - From, To : Integer) - return Boolean - with Ghost, Import; - function Hexa_To_Unsigned_Ghost (X : Character) return Uns - with Ghost, Import; - function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - return Uns_Option - with Ghost, Import; - function Is_Integer_Ghost (Str : String) return Boolean - with Ghost, Import; - procedure Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - with Ghost, Import; - procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) - with Ghost, Import; - function Abs_Uns_Of_Int (Val : Int) return Uns - with Ghost, Import; - function Value_Integer (Str : String) return Int - with Ghost, Import; - - package Int_Params is new Val_Util.Int_Params - (Int => Int, - Uns => Uns, - Uns_Option => Uns_Option, - Unsigned_Width_Ghost => Unsigned_Width_Ghost, - Wrap_Option => Wrap_Option, - Only_Decimal_Ghost => Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => Hexa_To_Unsigned_Ghost, - Scan_Based_Number_Ghost => Scan_Based_Number_Ghost, - Is_Integer_Ghost => Is_Integer_Ghost, - Prove_Iter_Scan_Based_Number_Ghost => Prove_Iter_Scan_Based_Number_Ghost, - Prove_Scan_Only_Decimal_Ghost => Prove_Scan_Only_Decimal_Ghost, - Abs_Uns_Of_Int => Abs_Uns_Of_Int, - Value_Integer => Value_Integer); - - package Image_I is new System.Image_I (Int_Params); + package Uns_Spec is new System.Value_U_Spec (Uns); + package Int_Spec is new System.Value_I_Spec (Int, Uns, Uns_Spec.Uns_Params); + + package Image_I is new System.Image_I + (Int => Int, + Uns => Uns, + Unsigned_Width_Ghost => Unsigned_Width_Ghost, + Int_Params => Int_Spec.Int_Params); procedure Set_Image_Integer (V : Int; diff --git a/gcc/ada/libgnat/s-imagei.adb b/gcc/ada/libgnat/s-imagei.adb index ff853d3..8997e3c 100644 --- a/gcc/ada/libgnat/s-imagei.adb +++ b/gcc/ada/libgnat/s-imagei.adb @@ -46,42 +46,6 @@ package body System.Image_I is Post => Ignore, Subprogram_Variant => Ignore); - -- As a use_clause for Int_Params cannot be used for instances of this - -- generic in System specs, rename all constants and subprograms. - - Unsigned_Width_Ghost : constant Natural := Int_Params.Unsigned_Width_Ghost; - - function Wrap_Option (Value : Uns) return Uns_Option - renames Int_Params.Wrap_Option; - function Only_Decimal_Ghost - (Str : String; - From, To : Integer) - return Boolean - renames Int_Params.Only_Decimal_Ghost; - function Hexa_To_Unsigned_Ghost (X : Character) return Uns - renames Int_Params.Hexa_To_Unsigned_Ghost; - function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - return Uns_Option - renames Int_Params.Scan_Based_Number_Ghost; - function Is_Integer_Ghost (Str : String) return Boolean - renames Int_Params.Is_Integer_Ghost; - procedure Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - renames Int_Params.Prove_Iter_Scan_Based_Number_Ghost; - procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) - renames Int_Params.Prove_Scan_Only_Decimal_Ghost; - function Abs_Uns_Of_Int (Val : Int) return Uns - renames Int_Params.Abs_Uns_Of_Int; - function Value_Integer (Str : String) return Int - renames Int_Params.Value_Integer; - subtype Non_Positive is Int range Int'First .. 0; function Uns_Of_Non_Positive (T : Non_Positive) return Uns is @@ -99,9 +63,9 @@ package body System.Image_I is and then P <= S'Last - Unsigned_Width_Ghost + 1, Post => S (S'First .. P'Old) = S'Old (S'First .. P'Old) and then P in P'Old + 1 .. S'Last - and then Only_Decimal_Ghost (S, From => P'Old + 1, To => P) - and then Scan_Based_Number_Ghost (S, From => P'Old + 1, To => P) - = Wrap_Option (Uns_Of_Non_Positive (T)); + and then UP.Only_Decimal_Ghost (S, From => P'Old + 1, To => P) + and then UP.Scan_Based_Number_Ghost (S, From => P'Old + 1, To => P) + = UP.Wrap_Option (Uns_Of_Non_Positive (T)); -- Set digits of absolute value of T, which is zero or negative. We work -- with the negative of the value so that the largest negative number is -- not a special case. @@ -182,11 +146,12 @@ package body System.Image_I is and then P in 2 .. S'Last and then S (1) in ' ' | '-' and then (S (1) = '-') = (V < 0) - and then Only_Decimal_Ghost (S, From => 2, To => P) - and then Scan_Based_Number_Ghost (S, From => 2, To => P) - = Wrap_Option (Abs_Uns_Of_Int (V)), - Post => Is_Integer_Ghost (S (1 .. P)) - and then Value_Integer (S (1 .. P)) = V; + and then UP.Only_Decimal_Ghost (S, From => 2, To => P) + and then UP.Scan_Based_Number_Ghost (S, From => 2, To => P) + = UP.Wrap_Option (IP.Abs_Uns_Of_Int (V)), + Post => not System.Val_Util.Only_Space_Ghost (S, 1, P) + and then IP.Is_Integer_Ghost (S (1 .. P)) + and then IP.Is_Value_Integer_Ghost (S (1 .. P), V); -- Ghost lemma to prove the value of Value_Integer from the value of -- Scan_Based_Number_Ghost and the sign on a decimal string. @@ -198,11 +163,14 @@ package body System.Image_I is Str : constant String := S (1 .. P); begin pragma Assert (Str'First = 1); - pragma Assert (Only_Decimal_Ghost (Str, From => 2, To => P)); - Prove_Iter_Scan_Based_Number_Ghost (S, Str, From => 2, To => P); - pragma Assert (Scan_Based_Number_Ghost (Str, From => 2, To => P) - = Wrap_Option (Abs_Uns_Of_Int (V))); - Prove_Scan_Only_Decimal_Ghost (Str, V); + pragma Assert (Str (2) /= ' '); + pragma Assert + (UP.Only_Decimal_Ghost (Str, From => 2, To => P)); + UP.Prove_Scan_Based_Number_Ghost_Eq (S, Str, From => 2, To => P); + pragma Assert + (UP.Scan_Based_Number_Ghost (Str, From => 2, To => P) + = UP.Wrap_Option (IP.Abs_Uns_Of_Int (V))); + IP.Prove_Scan_Only_Decimal_Ghost (Str, V); end Prove_Value_Integer; -- Start of processing for Image_Integer @@ -226,6 +194,8 @@ package body System.Image_I is pragma Assert (P_Prev + Offset = 2); end; + pragma Assert (if V >= 0 then S (1) = ' '); + pragma Assert (S (1) in ' ' | '-'); Prove_Value_Integer; end Image_Integer; @@ -248,42 +218,78 @@ package body System.Image_I is S_Init : constant String := S with Ghost; Uns_T : constant Uns := Uns_Of_Non_Positive (T) with Ghost; Uns_Value : Uns := Uns_Of_Non_Positive (Value) with Ghost; - Prev, Cur : Uns_Option with Ghost; Prev_Value : Uns with Ghost; Prev_S : String := S with Ghost; -- Local ghost lemmas - procedure Prove_Character_Val (RU : Uns; RI : Int) + procedure Prove_Character_Val (RU : Uns; RI : Non_Positive) with Ghost, - Pre => RU in 0 .. 9 - and then RI in 0 .. 9, - Post => Character'Val (48 + RU) in '0' .. '9' - and then Character'Val (48 + RI) in '0' .. '9'; + Post => RU rem 10 in 0 .. 9 + and then -(RI rem 10) in 0 .. 9 + and then Character'Val (48 + RU rem 10) in '0' .. '9' + and then Character'Val (48 - RI rem 10) in '0' .. '9'; -- Ghost lemma to prove the value of a character corresponding to the -- next figure. + procedure Prove_Euclidian (Val, Quot, Rest : Uns) + with + Ghost, + Pre => Quot = Val / 10 + and then Rest = Val rem 10, + Post => Uns'Last - Rest >= 10 * Quot and then Val = 10 * Quot + Rest; + -- Ghost lemma to prove the relation between the quotient/remainder of + -- division by 10 and the initial value. + procedure Prove_Hexa_To_Unsigned_Ghost (RU : Uns; RI : Int) with Ghost, Pre => RU in 0 .. 9 and then RI in 0 .. 9, - Post => Hexa_To_Unsigned_Ghost (Character'Val (48 + RU)) = RU - and then Hexa_To_Unsigned_Ghost (Character'Val (48 + RI)) = Uns (RI); + Post => UP.Hexa_To_Unsigned_Ghost + (Character'Val (48 + RU)) = RU + and then UP.Hexa_To_Unsigned_Ghost + (Character'Val (48 + RI)) = Uns (RI); -- Ghost lemma to prove that Hexa_To_Unsigned_Ghost returns the source -- figure when applied to the corresponding character. - procedure Prove_Unchanged - with - Ghost, - Pre => P <= S'Last - and then S_Init'First = S'First - and then S_Init'Last = S'Last - and then (for all K in S'First .. P => S (K) = S_Init (K)), - Post => S (S'First .. P) = S_Init (S'First .. P); - -- Ghost lemma to prove that the part of string S before P has not been - -- modified. + procedure Prove_Scan_Iter + (S, Prev_S : String; + V, Prev_V, Res : Uns; + P, Max : Natural) + with + Ghost, + Pre => + S'First = Prev_S'First and then S'Last = Prev_S'Last + and then S'Last < Natural'Last and then + Max in S'Range and then P in S'First .. Max and then + (for all I in P + 1 .. Max => Prev_S (I) in '0' .. '9') + and then (for all I in P + 1 .. Max => Prev_S (I) = S (I)) + and then S (P) in '0' .. '9' + and then V <= Uns'Last / 10 + and then Uns'Last - UP.Hexa_To_Unsigned_Ghost (S (P)) + >= 10 * V + and then Prev_V = + V * 10 + UP.Hexa_To_Unsigned_Ghost (S (P)) + and then + (if P = Max then Prev_V = Res + else UP.Scan_Based_Number_Ghost + (Str => Prev_S, + From => P + 1, + To => Max, + Base => 10, + Acc => Prev_V) = UP.Wrap_Option (Res)), + Post => + (for all I in P .. Max => S (I) in '0' .. '9') + and then UP.Scan_Based_Number_Ghost + (Str => S, + From => P, + To => Max, + Base => 10, + Acc => V) = UP.Wrap_Option (Res); + -- Ghost lemma to prove that Scan_Based_Number_Ghost is preserved + -- through an iteration of the loop. procedure Prove_Uns_Of_Non_Positive_Value with @@ -294,50 +300,44 @@ package body System.Image_I is -- Ghost lemma to prove that the relation between Value and its unsigned -- version is preserved. - procedure Prove_Iter_Scan - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - with - Ghost, - Pre => Str1'Last /= Positive'Last - and then - (From > To or else (From >= Str1'First and then To <= Str1'Last)) - and then Only_Decimal_Ghost (Str1, From, To) - and then Str1'First = Str2'First - and then Str1'Last = Str2'Last - and then (for all J in From .. To => Str1 (J) = Str2 (J)), - Post => - Scan_Based_Number_Ghost (Str1, From, To, Base, Acc) - = Scan_Based_Number_Ghost (Str2, From, To, Base, Acc); - -- Ghost lemma to prove that the result of Scan_Based_Number_Ghost only - -- depends on the value of the argument string in the (From .. To) range - -- of indexes. This is a wrapper on Prove_Iter_Scan_Based_Number_Ghost - -- so that we can call it here on ghost arguments. - ----------------------------- -- Local lemma null bodies -- ----------------------------- - procedure Prove_Character_Val (RU : Uns; RI : Int) is null; + procedure Prove_Character_Val (RU : Uns; RI : Non_Positive) is null; + procedure Prove_Euclidian (Val, Quot, Rest : Uns) is null; procedure Prove_Hexa_To_Unsigned_Ghost (RU : Uns; RI : Int) is null; - procedure Prove_Unchanged is null; procedure Prove_Uns_Of_Non_Positive_Value is null; --------------------- - -- Prove_Iter_Scan -- + -- Prove_Scan_Iter -- --------------------- - procedure Prove_Iter_Scan - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) + procedure Prove_Scan_Iter + (S, Prev_S : String; + V, Prev_V, Res : Uns; + P, Max : Natural) is + pragma Unreferenced (Res); begin - Prove_Iter_Scan_Based_Number_Ghost (Str1, Str2, From, To, Base, Acc); - end Prove_Iter_Scan; + UP.Lemma_Scan_Based_Number_Ghost_Step + (Str => S, + From => P, + To => Max, + Base => 10, + Acc => V); + if P < Max then + UP.Prove_Scan_Based_Number_Ghost_Eq + (Prev_S, S, P + 1, Max, 10, Prev_V); + else + UP.Lemma_Scan_Based_Number_Ghost_Base + (Str => S, + From => P + 1, + To => Max, + Base => 10, + Acc => Prev_V); + end if; + end Prove_Scan_Iter; -- Start of processing for Set_Digits @@ -383,13 +383,9 @@ package body System.Image_I is for J in reverse 1 .. Nb_Digits loop Lemma_Div_Commutation (Uns_Value, 10); Lemma_Div_Twice (Big (Uns_T), Big_10 ** (Nb_Digits - J), Big_10); - Prove_Character_Val (Uns_Value rem 10, -(Value rem 10)); + Prove_Character_Val (Uns_Value, Value); Prove_Hexa_To_Unsigned_Ghost (Uns_Value rem 10, -(Value rem 10)); Prove_Uns_Of_Non_Positive_Value; - pragma Assert (Uns_Value rem 10 = Uns_Of_Non_Positive (Value rem 10)); - pragma Assert (Uns_Value rem 10 = Uns (-(Value rem 10))); - pragma Assert - (Uns_Value = From_Big (Big (Uns_T) / Big_10 ** (Nb_Digits - J))); Prev_Value := Uns_Value; Prev_S := S; @@ -399,68 +395,44 @@ package body System.Image_I is S (P + J) := Character'Val (48 - (Value rem 10)); Value := Value / 10; - pragma Assert (S (P + J) in '0' .. '9'); - pragma Assert (Hexa_To_Unsigned_Ghost (S (P + J)) = - From_Big (Big (Uns_T) / Big_10 ** (Nb_Digits - J)) rem 10); - pragma Assert - (for all K in P + J + 1 .. P + Nb_Digits => S (K) in '0' .. '9'); + Prove_Euclidian + (Val => Prev_Value, + Quot => Uns_Value, + Rest => UP.Hexa_To_Unsigned_Ghost (S (P + J))); - Prev := Scan_Based_Number_Ghost - (Str => S, - From => P + J + 1, - To => P + Nb_Digits, - Base => 10, - Acc => Prev_Value); - Cur := Scan_Based_Number_Ghost - (Str => S, - From => P + J, - To => P + Nb_Digits, - Base => 10, - Acc => Uns_Value); - pragma Assert (Prev_Value = 10 * Uns_Value + (Prev_Value rem 10)); - pragma Assert - (Prev_Value rem 10 = Hexa_To_Unsigned_Ghost (S (P + J))); - pragma Assert - (Prev_Value = 10 * Uns_Value + Hexa_To_Unsigned_Ghost (S (P + J))); - - if J /= Nb_Digits then - Prove_Iter_Scan - (Prev_S, S, P + J + 1, P + Nb_Digits, 10, Prev_Value); - end if; - - pragma Assert (Prev = Cur); - pragma Assert (Prev = Wrap_Option (Uns_T)); + Prove_Scan_Iter + (S, Prev_S, Uns_Value, Prev_Value, Uns_T, P + J, P + Nb_Digits); pragma Loop_Invariant (Uns_Value = Uns_Of_Non_Positive (Value)); pragma Loop_Invariant (Uns_Value <= Uns'Last / 10); pragma Loop_Invariant (for all K in S'First .. P => S (K) = S_Init (K)); - pragma Loop_Invariant (Only_Decimal_Ghost (S, P + J, P + Nb_Digits)); + pragma Loop_Invariant + (UP.Only_Decimal_Ghost (S, P + J, P + Nb_Digits)); pragma Loop_Invariant (for all K in P + J .. P + Nb_Digits => S (K) in '0' .. '9'); pragma Loop_Invariant (Pow = Big_10 ** (Nb_Digits - J + 1)); pragma Loop_Invariant (Big (Uns_Value) = Big (Uns_T) / Pow); pragma Loop_Invariant - (Scan_Based_Number_Ghost + (UP.Scan_Based_Number_Ghost (Str => S, From => P + J, To => P + Nb_Digits, Base => 10, Acc => Uns_Value) - = Wrap_Option (Uns_T)); + = UP.Wrap_Option (Uns_T)); end loop; pragma Assert (Big (Uns_Value) = Big (Uns_T) / Big_10 ** (Nb_Digits)); pragma Assert (Uns_Value = 0); - Prove_Unchanged; pragma Assert - (Scan_Based_Number_Ghost + (UP.Scan_Based_Number_Ghost (Str => S, From => P + 1, To => P + Nb_Digits, Base => 10, Acc => Uns_Value) - = Wrap_Option (Uns_T)); + = UP.Wrap_Option (Uns_T)); P := P + Nb_Digits; end Set_Digits; diff --git a/gcc/ada/libgnat/s-imagei.ads b/gcc/ada/libgnat/s-imagei.ads index 10116d1..575c60a 100644 --- a/gcc/ada/libgnat/s-imagei.ads +++ b/gcc/ada/libgnat/s-imagei.ads @@ -48,19 +48,19 @@ pragma Assertion_Policy (Pre => Ignore, with System.Val_Util; generic + type Int is range <>; + type Uns is mod <>; - with package Int_Params is new System.Val_Util.Int_Params (<>); + Unsigned_Width_Ghost : Natural; -package System.Image_I is - - subtype Int is Int_Params.Int; - use type Int_Params.Int; + with package Int_Params is new System.Val_Util.Int_Params + (Int => Int, Uns => Uns, others => <>) + with Ghost; - subtype Uns is Int_Params.Uns; - use type Int_Params.Uns; - - subtype Uns_Option is Int_Params.Uns_Option; - use type Int_Params.Uns_Option; +package System.Image_I is + package IP renames Int_Params; + package UP renames IP.Uns_Params; + use type UP.Uns_Option; procedure Image_Integer (V : Int; @@ -69,9 +69,9 @@ package System.Image_I is with Pre => S'First = 1 and then S'Last < Integer'Last - and then S'Last >= Int_Params.Unsigned_Width_Ghost, + and then S'Last >= Unsigned_Width_Ghost, Post => P in S'Range - and then Int_Params.Value_Integer (S (1 .. P)) = V; + and then IP.Is_Value_Integer_Ghost (S (1 .. P), V); -- Computes Int'Image (V) and stores the result in S (1 .. P) -- setting the resulting value of P. The caller guarantees that S -- is long enough to hold the result, and that S'First is 1. @@ -87,23 +87,23 @@ package System.Image_I is and then S'First <= S'Last and then (if V >= 0 then - P <= S'Last - Int_Params.Unsigned_Width_Ghost + 1 + P <= S'Last - Unsigned_Width_Ghost + 1 else - P <= S'Last - Int_Params.Unsigned_Width_Ghost), + P <= S'Last - Unsigned_Width_Ghost), Post => S (S'First .. P'Old) = S'Old (S'First .. P'Old) and then (declare Minus : constant Boolean := S (P'Old + 1) = '-'; Offset : constant Positive := (if V >= 0 then 1 else 2); - Abs_V : constant Uns := Int_Params.Abs_Uns_Of_Int (V); + Abs_V : constant Uns := IP.Abs_Uns_Of_Int (V); begin Minus = (V < 0) and then P in P'Old + Offset .. S'Last - and then Int_Params.Only_Decimal_Ghost + and then UP.Only_Decimal_Ghost (S, From => P'Old + Offset, To => P) - and then Int_Params.Scan_Based_Number_Ghost + and then UP.Scan_Based_Number_Ghost (S, From => P'Old + Offset, To => P) - = Int_Params.Wrap_Option (Abs_V)); + = UP.Wrap_Option (Abs_V)); -- Stores the image of V in S starting at S (P + 1), P is updated to point -- to the last character stored. The value stored is identical to the value -- of Int'Image (V) except that no leading space is stored when V is diff --git a/gcc/ada/libgnat/s-imageu.adb b/gcc/ada/libgnat/s-imageu.adb index 6932487..0e1c2bb 100644 --- a/gcc/ada/libgnat/s-imageu.adb +++ b/gcc/ada/libgnat/s-imageu.adb @@ -147,11 +147,12 @@ package body System.Image_U is and then S'Last < Integer'Last and then P in 2 .. S'Last and then S (1) = ' ' - and then Only_Decimal_Ghost (S, From => 2, To => P) - and then Scan_Based_Number_Ghost (S, From => 2, To => P) - = Wrap_Option (V), - Post => Is_Unsigned_Ghost (S (1 .. P)) - and then Value_Unsigned (S (1 .. P)) = V; + and then Uns_Params.Only_Decimal_Ghost (S, From => 2, To => P) + and then Uns_Params.Scan_Based_Number_Ghost (S, From => 2, To => P) + = Uns_Params.Wrap_Option (V), + Post => not System.Val_Util.Only_Space_Ghost (S, 1, P) + and then Uns_Params.Is_Unsigned_Ghost (S (1 .. P)) + and then Uns_Params.Is_Value_Unsigned_Ghost (S (1 .. P), V); -- Ghost lemma to prove the value of Value_Unsigned from the value of -- Scan_Based_Number_Ghost on a decimal string. @@ -163,11 +164,15 @@ package body System.Image_U is Str : constant String := S (1 .. P); begin pragma Assert (Str'First = 1); - pragma Assert (Only_Decimal_Ghost (Str, From => 2, To => P)); - Prove_Iter_Scan_Based_Number_Ghost (S, Str, From => 2, To => P); - pragma Assert (Scan_Based_Number_Ghost (Str, From => 2, To => P) - = Wrap_Option (V)); - Prove_Scan_Only_Decimal_Ghost (Str, V); + pragma Assert (S (2) /= ' '); + pragma Assert + (Uns_Params.Only_Decimal_Ghost (Str, From => 2, To => P)); + Uns_Params.Prove_Scan_Based_Number_Ghost_Eq + (S, Str, From => 2, To => P); + pragma Assert + (Uns_Params.Scan_Based_Number_Ghost (Str, From => 2, To => P) + = Uns_Params.Wrap_Option (V)); + Uns_Params.Prove_Scan_Only_Decimal_Ghost (Str, V); end Prove_Value_Unsigned; -- Start of processing for Image_Unsigned @@ -196,7 +201,6 @@ package body System.Image_U is Pow : Big_Positive := 1 with Ghost; S_Init : constant String := S with Ghost; - Prev, Cur : Uns_Option with Ghost; Prev_Value : Uns with Ghost; Prev_S : String := S with Ghost; @@ -205,8 +209,8 @@ package body System.Image_U is procedure Prove_Character_Val (R : Uns) with Ghost, - Pre => R in 0 .. 9, - Post => Character'Val (48 + R) in '0' .. '9'; + Post => R rem 10 in 0 .. 9 + and then Character'Val (48 + R rem 10) in '0' .. '9'; -- Ghost lemma to prove the value of a character corresponding to the -- next figure. @@ -215,7 +219,7 @@ package body System.Image_U is Ghost, Pre => Quot = Val / 10 and then Rest = Val rem 10, - Post => Val = 10 * Quot + Rest; + Post => Uns'Last - Rest >= 10 * Quot and then Val = 10 * Quot + Rest; -- Ghost lemma to prove the relation between the quotient/remainder of -- division by 10 and the initial value. @@ -223,42 +227,46 @@ package body System.Image_U is with Ghost, Pre => R in 0 .. 9, - Post => Hexa_To_Unsigned_Ghost (Character'Val (48 + R)) = R; + Post => Uns_Params.Hexa_To_Unsigned_Ghost (Character'Val (48 + R)) = R; -- Ghost lemma to prove that Hexa_To_Unsigned_Ghost returns the source -- figure when applied to the corresponding character. - procedure Prove_Unchanged - with - Ghost, - Pre => P <= S'Last - and then S_Init'First = S'First - and then S_Init'Last = S'Last - and then (for all K in S'First .. P => S (K) = S_Init (K)), - Post => S (S'First .. P) = S_Init (S'First .. P); - -- Ghost lemma to prove that the part of string S before P has not been - -- modified. - - procedure Prove_Iter_Scan - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - with - Ghost, - Pre => Str1'Last /= Positive'Last - and then - (From > To or else (From >= Str1'First and then To <= Str1'Last)) - and then Only_Decimal_Ghost (Str1, From, To) - and then Str1'First = Str2'First - and then Str1'Last = Str2'Last - and then (for all J in From .. To => Str1 (J) = Str2 (J)), - Post => - Scan_Based_Number_Ghost (Str1, From, To, Base, Acc) - = Scan_Based_Number_Ghost (Str2, From, To, Base, Acc); - -- Ghost lemma to prove that the result of Scan_Based_Number_Ghost only - -- depends on the value of the argument string in the (From .. To) range - -- of indexes. This is a wrapper on Prove_Iter_Scan_Based_Number_Ghost - -- so that we can call it here on ghost arguments. + procedure Prove_Scan_Iter + (S, Prev_S : String; + V, Prev_V, Res : Uns; + P, Max : Natural) + with + Ghost, + Pre => + S'First = Prev_S'First and then S'Last = Prev_S'Last + and then S'Last < Natural'Last and then + Max in S'Range and then P in S'First .. Max and then + (for all I in P + 1 .. Max => Prev_S (I) in '0' .. '9') + and then (for all I in P + 1 .. Max => Prev_S (I) = S (I)) + and then S (P) in '0' .. '9' + and then V <= Uns'Last / 10 + and then Uns'Last - Uns_Params.Hexa_To_Unsigned_Ghost (S (P)) + >= 10 * V + and then Prev_V = + V * 10 + Uns_Params.Hexa_To_Unsigned_Ghost (S (P)) + and then + (if P = Max then Prev_V = Res + else Uns_Params.Scan_Based_Number_Ghost + (Str => Prev_S, + From => P + 1, + To => Max, + Base => 10, + Acc => Prev_V) = Uns_Params.Wrap_Option (Res)), + Post => + (for all I in P .. Max => S (I) in '0' .. '9') + and then Uns_Params.Scan_Based_Number_Ghost + (Str => S, + From => P, + To => Max, + Base => 10, + Acc => V) = Uns_Params.Wrap_Option (Res); + -- Ghost lemma to prove that Scan_Based_Number_Ghost is preserved + -- through an iteration of the loop. ----------------------------- -- Local lemma null bodies -- @@ -267,21 +275,36 @@ package body System.Image_U is procedure Prove_Character_Val (R : Uns) is null; procedure Prove_Euclidian (Val, Quot, Rest : Uns) is null; procedure Prove_Hexa_To_Unsigned_Ghost (R : Uns) is null; - procedure Prove_Unchanged is null; --------------------- - -- Prove_Iter_Scan -- + -- Prove_Scan_Iter -- --------------------- - procedure Prove_Iter_Scan - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) + procedure Prove_Scan_Iter + (S, Prev_S : String; + V, Prev_V, Res : Uns; + P, Max : Natural) is + pragma Unreferenced (Res); begin - Prove_Iter_Scan_Based_Number_Ghost (Str1, Str2, From, To, Base, Acc); - end Prove_Iter_Scan; + Uns_Params.Lemma_Scan_Based_Number_Ghost_Step + (Str => S, + From => P, + To => Max, + Base => 10, + Acc => V); + if P < Max then + Uns_Params.Prove_Scan_Based_Number_Ghost_Eq + (Prev_S, S, P + 1, Max, 10, Prev_V); + else + Uns_Params.Lemma_Scan_Based_Number_Ghost_Base + (Str => S, + From => P + 1, + To => Max, + Base => 10, + Acc => Prev_V); + end if; + end Prove_Scan_Iter; -- Start of processing for Set_Image_Unsigned @@ -313,6 +336,7 @@ package body System.Image_U is Lemma_Non_Zero (Value); pragma Assert (Pow <= Big (Uns'Last)); end loop; + pragma Assert (Big (V) / (Big_10 ** Nb_Digits) = 0); Value := V; Pow := 1; @@ -323,77 +347,43 @@ package body System.Image_U is for J in reverse 1 .. Nb_Digits loop Lemma_Div_Commutation (Value, 10); Lemma_Div_Twice (Big (V), Big_10 ** (Nb_Digits - J), Big_10); - Prove_Character_Val (Value rem 10); + Prove_Character_Val (Value); Prove_Hexa_To_Unsigned_Ghost (Value rem 10); Prev_Value := Value; Prev_S := S; Pow := Pow * 10; - S (P + J) := Character'Val (48 + (Value rem 10)); Value := Value / 10; - pragma Assert (S (P + J) in '0' .. '9'); - pragma Assert (Hexa_To_Unsigned_Ghost (S (P + J)) = - From_Big (Big (V) / Big_10 ** (Nb_Digits - J)) rem 10); - pragma Assert - (for all K in P + J + 1 .. P + Nb_Digits => S (K) in '0' .. '9'); - pragma Assert - (for all K in P + J + 1 .. P + Nb_Digits => - Hexa_To_Unsigned_Ghost (S (K)) = - From_Big (Big (V) / Big_10 ** (Nb_Digits - (K - P))) rem 10); - - Prev := Scan_Based_Number_Ghost - (Str => S, - From => P + J + 1, - To => P + Nb_Digits, - Base => 10, - Acc => Prev_Value); - Cur := Scan_Based_Number_Ghost - (Str => S, - From => P + J, - To => P + Nb_Digits, - Base => 10, - Acc => Value); - - if J /= Nb_Digits then - Prove_Euclidian (Val => Prev_Value, - Quot => Value, - Rest => Hexa_To_Unsigned_Ghost (S (P + J))); - pragma Assert - (Prev_Value = 10 * Value + Hexa_To_Unsigned_Ghost (S (P + J))); - Prove_Iter_Scan - (Prev_S, S, P + J + 1, P + Nb_Digits, 10, Prev_Value); - end if; + Prove_Euclidian + (Val => Prev_Value, + Quot => Value, + Rest => Uns_Params.Hexa_To_Unsigned_Ghost (S (P + J))); - pragma Assert (Prev = Cur); - pragma Assert (Prev = Wrap_Option (V)); + Prove_Scan_Iter + (S, Prev_S, Value, Prev_Value, V, P + J, P + Nb_Digits); pragma Loop_Invariant (Value <= Uns'Last / 10); pragma Loop_Invariant (for all K in S'First .. P => S (K) = S_Init (K)); - pragma Loop_Invariant (Only_Decimal_Ghost (S, P + J, P + Nb_Digits)); - pragma Loop_Invariant - (for all K in P + J .. P + Nb_Digits => S (K) in '0' .. '9'); pragma Loop_Invariant - (for all K in P + J .. P + Nb_Digits => - Hexa_To_Unsigned_Ghost (S (K)) = - From_Big (Big (V) / Big_10 ** (Nb_Digits - (K - P))) rem 10); + (Uns_Params.Only_Decimal_Ghost + (S, From => P + J, To => P + Nb_Digits)); pragma Loop_Invariant (Pow = Big_10 ** (Nb_Digits - J + 1)); pragma Loop_Invariant (Big (Value) = Big (V) / Pow); pragma Loop_Invariant - (Scan_Based_Number_Ghost + (Uns_Params.Scan_Based_Number_Ghost (Str => S, From => P + J, To => P + Nb_Digits, Base => 10, Acc => Value) - = Wrap_Option (V)); + = Uns_Params.Wrap_Option (V)); end loop; + pragma Assert (Big (Value) = Big (V) / (Big_10 ** Nb_Digits)); pragma Assert (Value = 0); - Prove_Unchanged; - P := P + Nb_Digits; end Set_Image_Unsigned; diff --git a/gcc/ada/libgnat/s-imageu.ads b/gcc/ada/libgnat/s-imageu.ads index 789cf65..3d80ea9 100644 --- a/gcc/ada/libgnat/s-imageu.ads +++ b/gcc/ada/libgnat/s-imageu.ads @@ -45,45 +45,22 @@ pragma Assertion_Policy (Pre => Ignore, Ghost => Ignore, Subprogram_Variant => Ignore); +with System.Val_Util; + generic type Uns is mod <>; - type Uns_Option is private; -- Additional parameters for ghost subprograms used inside contracts Unsigned_Width_Ghost : Natural; - with function Wrap_Option (Value : Uns) return Uns_Option - with Ghost; - with function Only_Decimal_Ghost - (Str : String; - From, To : Integer) - return Boolean - with Ghost; - with function Hexa_To_Unsigned_Ghost (X : Character) return Uns - with Ghost; - with function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) return Uns_Option - with Ghost; - with function Is_Unsigned_Ghost (Str : String) return Boolean - with Ghost; - with function Value_Unsigned (Str : String) return Uns; - with procedure Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - with Ghost; - with procedure Prove_Scan_Only_Decimal_Ghost - (Str : String; - Val : Uns) - with Ghost; + with package Uns_Params is new System.Val_Util.Uns_Params + (Uns => Uns, others => <>) + with Ghost; package System.Image_U is + use all type Uns_Params.Uns_Option; procedure Image_Unsigned (V : Uns; @@ -94,7 +71,7 @@ package System.Image_U is and then S'Last < Integer'Last and then S'Last >= Unsigned_Width_Ghost, Post => P in S'Range - and then Value_Unsigned (S (1 .. P)) = V; + and then Uns_Params.Is_Value_Unsigned_Ghost (S (1 .. P), V); pragma Inline (Image_Unsigned); -- Computes Uns'Image (V) and stores the result in S (1 .. P) setting -- the resulting value of P. The caller guarantees that S is long enough to @@ -112,9 +89,10 @@ package System.Image_U is and then P <= S'Last - Unsigned_Width_Ghost + 1, Post => S (S'First .. P'Old) = S'Old (S'First .. P'Old) and then P in P'Old + 1 .. S'Last - and then Only_Decimal_Ghost (S, From => P'Old + 1, To => P) - and then Scan_Based_Number_Ghost (S, From => P'Old + 1, To => P) - = Wrap_Option (V); + and then Uns_Params.Only_Decimal_Ghost (S, From => P'Old + 1, To => P) + and then Uns_Params.Scan_Based_Number_Ghost + (S, From => P'Old + 1, To => P) + = Uns_Params.Wrap_Option (V); -- Stores the image of V in S starting at S (P + 1), P is updated to point -- to the last character stored. The value stored is identical to the value -- of Uns'Image (V) except that no leading space is stored. The caller diff --git a/gcc/ada/libgnat/s-imgint.ads b/gcc/ada/libgnat/s-imgint.ads index fd5bea3..8672e58 100644 --- a/gcc/ada/libgnat/s-imgint.ads +++ b/gcc/ada/libgnat/s-imgint.ads @@ -48,8 +48,6 @@ pragma Assertion_Policy (Pre => Ignore, with System.Image_I; with System.Unsigned_Types; with System.Val_Int; -with System.Val_Uns; -with System.Val_Util; with System.Wid_Uns; package System.Img_Int @@ -57,27 +55,12 @@ package System.Img_Int is subtype Unsigned is Unsigned_Types.Unsigned; - package Int_Params is new Val_Util.Int_Params - (Int => Integer, - Uns => Unsigned, - Uns_Option => Val_Uns.Impl.Uns_Option, - Unsigned_Width_Ghost => + package Impl is new Image_I + (Int => Integer, + Uns => Unsigned, + Unsigned_Width_Ghost => Wid_Uns.Width_Unsigned (0, Unsigned'Last), - Only_Decimal_Ghost => Val_Uns.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_Uns.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_Uns.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_Uns.Impl.Scan_Based_Number_Ghost, - Prove_Iter_Scan_Based_Number_Ghost => - Val_Uns.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Is_Integer_Ghost => Val_Int.Impl.Is_Integer_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_Int.Impl.Prove_Scan_Only_Decimal_Ghost, - Abs_Uns_Of_Int => Val_Int.Impl.Abs_Uns_Of_Int, - Value_Integer => Val_Int.Impl.Value_Integer); - - package Impl is new Image_I (Int_Params); + Int_Params => System.Val_Int.Impl.Spec.Int_Params); procedure Image_Integer (V : Integer; diff --git a/gcc/ada/libgnat/s-imglli.ads b/gcc/ada/libgnat/s-imglli.ads index 20f108c..99c1951 100644 --- a/gcc/ada/libgnat/s-imglli.ads +++ b/gcc/ada/libgnat/s-imglli.ads @@ -48,8 +48,6 @@ pragma Assertion_Policy (Pre => Ignore, with System.Image_I; with System.Unsigned_Types; with System.Val_LLI; -with System.Val_LLU; -with System.Val_Util; with System.Wid_LLU; package System.Img_LLI @@ -57,27 +55,13 @@ package System.Img_LLI is subtype Long_Long_Unsigned is Unsigned_Types.Long_Long_Unsigned; - package Int_Params is new Val_Util.Int_Params - (Int => Long_Long_Integer, - Uns => Long_Long_Unsigned, - Uns_Option => Val_LLU.Impl.Uns_Option, - Unsigned_Width_Ghost => - Wid_LLU.Width_Long_Long_Unsigned (0, Long_Long_Unsigned'Last), - Only_Decimal_Ghost => Val_LLU.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_LLU.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_LLU.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_LLU.Impl.Scan_Based_Number_Ghost, - Prove_Iter_Scan_Based_Number_Ghost => - Val_LLU.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Is_Integer_Ghost => Val_LLI.Impl.Is_Integer_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_LLI.Impl.Prove_Scan_Only_Decimal_Ghost, - Abs_Uns_Of_Int => Val_LLI.Impl.Abs_Uns_Of_Int, - Value_Integer => Val_LLI.Impl.Value_Integer); - - package Impl is new Image_I (Int_Params); + package Impl is new Image_I + (Int => Long_Long_Integer, + Uns => Long_Long_Unsigned, + Unsigned_Width_Ghost => + Wid_LLU.Width_Long_Long_Unsigned + (0, Long_Long_Unsigned'Last), + Int_Params => System.Val_LLI.Impl.Spec.Int_Params); procedure Image_Long_Long_Integer (V : Long_Long_Integer; diff --git a/gcc/ada/libgnat/s-imgllli.ads b/gcc/ada/libgnat/s-imgllli.ads index 989c296..931c288 100644 --- a/gcc/ada/libgnat/s-imgllli.ads +++ b/gcc/ada/libgnat/s-imgllli.ads @@ -48,8 +48,6 @@ pragma Assertion_Policy (Pre => Ignore, with System.Image_I; with System.Unsigned_Types; with System.Val_LLLI; -with System.Val_LLLU; -with System.Val_Util; with System.Wid_LLLU; package System.Img_LLLI @@ -57,28 +55,13 @@ package System.Img_LLLI is subtype Long_Long_Long_Unsigned is Unsigned_Types.Long_Long_Long_Unsigned; - package Int_Params is new Val_Util.Int_Params - (Int => Long_Long_Long_Integer, - Uns => Long_Long_Long_Unsigned, - Uns_Option => Val_LLLU.Impl.Uns_Option, - Unsigned_Width_Ghost => + package Impl is new Image_I + (Int => Long_Long_Long_Integer, + Uns => Long_Long_Long_Unsigned, + Unsigned_Width_Ghost => Wid_LLLU.Width_Long_Long_Long_Unsigned (0, Long_Long_Long_Unsigned'Last), - Only_Decimal_Ghost => Val_LLLU.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_LLLU.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_LLLU.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_LLLU.Impl.Scan_Based_Number_Ghost, - Prove_Iter_Scan_Based_Number_Ghost => - Val_LLLU.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Is_Integer_Ghost => Val_LLLI.Impl.Is_Integer_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_LLLI.Impl.Prove_Scan_Only_Decimal_Ghost, - Abs_Uns_Of_Int => Val_LLLI.Impl.Abs_Uns_Of_Int, - Value_Integer => Val_LLLI.Impl.Value_Integer); - - package Impl is new Image_I (Int_Params); + Int_Params => System.Val_LLLI.Impl.Spec.Int_Params); procedure Image_Long_Long_Long_Integer (V : Long_Long_Long_Integer; diff --git a/gcc/ada/libgnat/s-imglllu.ads b/gcc/ada/libgnat/s-imglllu.ads index 0116aa8..53b39a8 100644 --- a/gcc/ada/libgnat/s-imglllu.ads +++ b/gcc/ada/libgnat/s-imglllu.ads @@ -56,23 +56,11 @@ is subtype Long_Long_Long_Unsigned is Unsigned_Types.Long_Long_Long_Unsigned; package Impl is new Image_U - (Uns => Long_Long_Long_Unsigned, - Uns_Option => Val_LLLU.Impl.Uns_Option, - Unsigned_Width_Ghost => + (Uns => Long_Long_Long_Unsigned, + Unsigned_Width_Ghost => Wid_LLLU.Width_Long_Long_Long_Unsigned (0, Long_Long_Long_Unsigned'Last), - Only_Decimal_Ghost => Val_LLLU.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_LLLU.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_LLLU.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_LLLU.Impl.Scan_Based_Number_Ghost, - Is_Unsigned_Ghost => Val_LLLU.Impl.Is_Unsigned_Ghost, - Value_Unsigned => Val_LLLU.Impl.Value_Unsigned, - Prove_Iter_Scan_Based_Number_Ghost => - Val_LLLU.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_LLLU.Impl.Prove_Scan_Only_Decimal_Ghost); + Uns_Params => System.Val_LLLU.Impl.Spec.Uns_Params); procedure Image_Long_Long_Long_Unsigned (V : Long_Long_Long_Unsigned; diff --git a/gcc/ada/libgnat/s-imgllu.ads b/gcc/ada/libgnat/s-imgllu.ads index 67372d7..28339cd 100644 --- a/gcc/ada/libgnat/s-imgllu.ads +++ b/gcc/ada/libgnat/s-imgllu.ads @@ -56,22 +56,10 @@ is subtype Long_Long_Unsigned is Unsigned_Types.Long_Long_Unsigned; package Impl is new Image_U - (Uns => Long_Long_Unsigned, - Uns_Option => Val_LLU.Impl.Uns_Option, - Unsigned_Width_Ghost => + (Uns => Long_Long_Unsigned, + Unsigned_Width_Ghost => Wid_LLU.Width_Long_Long_Unsigned (0, Long_Long_Unsigned'Last), - Only_Decimal_Ghost => Val_LLU.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_LLU.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_LLU.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_LLU.Impl.Scan_Based_Number_Ghost, - Is_Unsigned_Ghost => Val_LLU.Impl.Is_Unsigned_Ghost, - Value_Unsigned => Val_LLU.Impl.Value_Unsigned, - Prove_Iter_Scan_Based_Number_Ghost => - Val_LLU.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_LLU.Impl.Prove_Scan_Only_Decimal_Ghost); + Uns_Params => System.Val_LLU.Impl.Spec.Uns_Params); procedure Image_Long_Long_Unsigned (V : Long_Long_Unsigned; diff --git a/gcc/ada/libgnat/s-imguns.ads b/gcc/ada/libgnat/s-imguns.ads index fa903ce..120bd5d 100644 --- a/gcc/ada/libgnat/s-imguns.ads +++ b/gcc/ada/libgnat/s-imguns.ads @@ -56,22 +56,10 @@ is subtype Unsigned is Unsigned_Types.Unsigned; package Impl is new Image_U - (Uns => Unsigned, - Uns_Option => Val_Uns.Impl.Uns_Option, - Unsigned_Width_Ghost => + (Uns => Unsigned, + Unsigned_Width_Ghost => Wid_Uns.Width_Unsigned (0, Unsigned'Last), - Only_Decimal_Ghost => Val_Uns.Impl.Only_Decimal_Ghost, - Hexa_To_Unsigned_Ghost => - Val_Uns.Impl.Hexa_To_Unsigned_Ghost, - Wrap_Option => Val_Uns.Impl.Wrap_Option, - Scan_Based_Number_Ghost => - Val_Uns.Impl.Scan_Based_Number_Ghost, - Is_Unsigned_Ghost => Val_Uns.Impl.Is_Unsigned_Ghost, - Value_Unsigned => Val_Uns.Impl.Value_Unsigned, - Prove_Iter_Scan_Based_Number_Ghost => - Val_Uns.Impl.Prove_Iter_Scan_Based_Number_Ghost, - Prove_Scan_Only_Decimal_Ghost => - Val_Uns.Impl.Prove_Scan_Only_Decimal_Ghost); + Uns_Params => System.Val_Uns.Impl.Spec.Uns_Params); procedure Image_Unsigned (V : Unsigned; diff --git a/gcc/ada/libgnat/s-vaispe.adb b/gcc/ada/libgnat/s-vaispe.adb new file mode 100644 index 0000000..dca2fd7 --- /dev/null +++ b/gcc/ada/libgnat/s-vaispe.adb @@ -0,0 +1,87 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . V A L U E _ I _ S P E C -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2022-2022, Free Software Foundation, Inc. -- +-- -- +-- GNAT 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/>. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +pragma Assertion_Policy (Pre => Ignore, + Post => Ignore, + Contract_Cases => Ignore, + Ghost => Ignore, + Subprogram_Variant => Ignore); + +package body System.Value_I_Spec is + + ----------------------------------- + -- Prove_Scan_Only_Decimal_Ghost -- + ----------------------------------- + + procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) is + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + pragma Assert (Str (Str'First + 1) /= ' '); + pragma Assert + (if Val < 0 then Non_Blank = Str'First + else + Str (Str'First) = ' ' + and then Non_Blank = Str'First + 1); + Minus : constant Boolean := Str (Non_Blank) = '-'; + Fst_Num : constant Positive := + (if Minus then Non_Blank + 1 else Non_Blank); + pragma Assert (Fst_Num = Str'First + 1); + Uval : constant Uns := Abs_Uns_Of_Int (Val); + + procedure Prove_Conversion_Is_Identity (Val : Int; Uval : Uns) + with + Pre => Minus = (Val < 0) + and then Uval = Abs_Uns_Of_Int (Val), + Post => Uns_Is_Valid_Int (Minus, Uval) + and then Is_Int_Of_Uns (Minus, Uval, Val); + -- Local proof of the unicity of the signed representation + + procedure Prove_Conversion_Is_Identity (Val : Int; Uval : Uns) is null; + + -- Start of processing for Prove_Scan_Only_Decimal_Ghost + + begin + Prove_Conversion_Is_Identity (Val, Uval); + pragma Assert + (Uns_Params.Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))); + pragma Assert + (Uns_Params.Scan_Split_No_Overflow_Ghost (Str, Fst_Num, Str'Last)); + Uns_Params.Lemma_Exponent_Unsigned_Ghost_Base (Uval, 0, 10); + pragma Assert + (Uns_Params.Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Str'Last)); + pragma Assert (Only_Space_Ghost + (Str, Uns_Params.Raw_Unsigned_Last_Ghost + (Str, Fst_Num, Str'Last), Str'Last)); + pragma Assert (Is_Integer_Ghost (Str)); + pragma Assert (Is_Value_Integer_Ghost (Str, Val)); + end Prove_Scan_Only_Decimal_Ghost; + +end System.Value_I_Spec; diff --git a/gcc/ada/libgnat/s-vaispe.ads b/gcc/ada/libgnat/s-vaispe.ads new file mode 100644 index 0000000..5a5e051 --- /dev/null +++ b/gcc/ada/libgnat/s-vaispe.ads @@ -0,0 +1,199 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . V A L U E _ I _ S P E C -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2022-2022, Free Software Foundation, Inc. -- +-- -- +-- GNAT 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/>. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This package contains the specification entities using for the formal +-- verification of the routines for scanning signed integer values. + +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. Postconditions and +-- contract cases should not be executed at runtime as well, in order not to +-- slow down the execution of these functions. + +pragma Assertion_Policy (Pre => Ignore, + Post => Ignore, + Contract_Cases => Ignore, + Ghost => Ignore, + Subprogram_Variant => Ignore); + +with System.Val_Util; use System.Val_Util; + +generic + + type Int is range <>; + + type Uns is mod <>; + + -- Additional parameters for specification subprograms on modular Unsigned + -- integers. + + with package Uns_Params is new System.Val_Util.Uns_Params + (Uns => Uns, others => <>) + with Ghost; + +package System.Value_I_Spec with + Ghost, + SPARK_Mode, + Annotate => (GNATprove, Always_Return) +is + pragma Preelaborate; + use all type Uns_Params.Uns_Option; + + function Uns_Is_Valid_Int (Minus : Boolean; Uval : Uns) return Boolean is + (if Minus then Uval <= Uns (Int'Last) + 1 + else Uval <= Uns (Int'Last)) + with Post => True; + -- Return True if Uval (or -Uval when Minus is True) is a valid number of + -- type Int. + + function Is_Int_Of_Uns + (Minus : Boolean; + Uval : Uns; + Val : Int) + return Boolean + is + (if Minus and then Uval = Uns (Int'Last) + 1 then Val = Int'First + elsif Minus then Val = -(Int (Uval)) + else Val = Int (Uval)) + with + Pre => Uns_Is_Valid_Int (Minus, Uval), + Post => True; + -- Return True if Uval (or -Uval when Minus is True) is equal to Val + + function Abs_Uns_Of_Int (Val : Int) return Uns is + (if Val = Int'First then Uns (Int'Last) + 1 + elsif Val < 0 then Uns (-Val) + else Uns (Val)); + -- Return the unsigned absolute value of Val + + function Slide_To_1 (Str : String) return String + with + Post => + Only_Space_Ghost (Str, Str'First, Str'Last) = + (for all J in Str'First .. Str'Last => + Slide_To_1'Result (J - Str'First + 1) = ' '); + -- Slides Str so that it starts at 1 + + function Slide_If_Necessary (Str : String) return String is + (if Str'Last = Positive'Last then Slide_To_1 (Str) else Str); + -- If Str'Last = Positive'Last then slides Str so that it starts at 1 + + function Is_Integer_Ghost (Str : String) return Boolean is + (declare + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + Fst_Num : constant Positive := + (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); + begin + Uns_Params.Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last)) + and then Uns_Params.Raw_Unsigned_No_Overflow_Ghost + (Str, Fst_Num, Str'Last) + and then + Uns_Is_Valid_Int + (Minus => Str (Non_Blank) = '-', + Uval => Uns_Params.Scan_Raw_Unsigned_Ghost + (Str, Fst_Num, Str'Last)) + and then Only_Space_Ghost + (Str, Uns_Params.Raw_Unsigned_Last_Ghost + (Str, Fst_Num, Str'Last), Str'Last)) + with + Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Str'Last /= Positive'Last, + Post => True; + -- Ghost function that determines if Str has the correct format for a + -- signed number, consisting in some blank characters, an optional + -- sign, a raw unsigned number which does not overflow and then some + -- more blank characters. + + function Is_Value_Integer_Ghost (Str : String; Val : Int) return Boolean is + (declare + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + Fst_Num : constant Positive := + (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); + Uval : constant Uns := + Uns_Params.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last); + begin + Is_Int_Of_Uns (Minus => Str (Non_Blank) = '-', + Uval => Uval, + Val => Val)) + with + Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Str'Last /= Positive'Last + and then Is_Integer_Ghost (Str), + Post => True; + -- Ghost function that returns True if Val is the value corresponding to + -- the signed number represented by Str. + + procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) + with + Ghost, + Pre => Str'Last /= Positive'Last + and then Str'Length >= 2 + and then Str (Str'First) in ' ' | '-' + and then (Str (Str'First) = '-') = (Val < 0) + and then Uns_Params.Only_Decimal_Ghost (Str, Str'First + 1, Str'Last) + and then Uns_Params.Scan_Based_Number_Ghost + (Str, Str'First + 1, Str'Last) + = Uns_Params.Wrap_Option (Abs_Uns_Of_Int (Val)), + Post => Is_Integer_Ghost (Slide_If_Necessary (Str)) + and then Is_Value_Integer_Ghost (Str, Val); + -- Ghost lemma used in the proof of 'Image implementation, to prove that + -- the result of Value_Integer on a decimal string is the same as the + -- signing the result of Scan_Based_Number_Ghost. + + -- Bundle Int type with other types, constants and subprograms used in + -- ghost code, so that this package can be instantiated once and used + -- multiple times as generic formal for a given Int type. + + package Int_Params is new System.Val_Util.Int_Params + (Uns => Uns, + Int => Int, + P_Uns_Params => Uns_Params, + P_Is_Integer_Ghost => Is_Integer_Ghost, + P_Is_Value_Integer_Ghost => Is_Value_Integer_Ghost, + P_Is_Int_Of_Uns => Is_Int_Of_Uns, + P_Abs_Uns_Of_Int => Abs_Uns_Of_Int, + P_Prove_Scan_Only_Decimal_Ghost => Prove_Scan_Only_Decimal_Ghost); + +private + + ---------------- + -- Slide_To_1 -- + ---------------- + + function Slide_To_1 (Str : String) return String is + (declare + Res : constant String (1 .. Str'Length) := Str; + begin + Res); + +end System.Value_I_Spec; diff --git a/gcc/ada/libgnat/s-valint.ads b/gcc/ada/libgnat/s-valint.ads index 9e47f1b..3872d7c 100644 --- a/gcc/ada/libgnat/s-valint.ads +++ b/gcc/ada/libgnat/s-valint.ads @@ -54,23 +54,10 @@ package System.Val_Int with SPARK_Mode is subtype Unsigned is Unsigned_Types.Unsigned; package Impl is new Value_I - (Int => Integer, - Uns => Unsigned, - Scan_Raw_Unsigned => Val_Uns.Scan_Raw_Unsigned, - Uns_Option => Val_Uns.Impl.Uns_Option, - Wrap_Option => Val_Uns.Impl.Wrap_Option, - Is_Raw_Unsigned_Format_Ghost => - Val_Uns.Impl.Is_Raw_Unsigned_Format_Ghost, - Raw_Unsigned_Overflows_Ghost => - Val_Uns.Impl.Raw_Unsigned_Overflows_Ghost, - Scan_Raw_Unsigned_Ghost => - Val_Uns.Impl.Scan_Raw_Unsigned_Ghost, - Raw_Unsigned_Last_Ghost => - Val_Uns.Impl.Raw_Unsigned_Last_Ghost, - Only_Decimal_Ghost => - Val_Uns.Impl.Only_Decimal_Ghost, - Scan_Based_Number_Ghost => - Val_Uns.Impl.Scan_Based_Number_Ghost); + (Int => Integer, + Uns => Unsigned, + Scan_Raw_Unsigned => Val_Uns.Scan_Raw_Unsigned, + Uns_Params => System.Val_Uns.Impl.Spec.Uns_Params); procedure Scan_Integer (Str : String; diff --git a/gcc/ada/libgnat/s-vallli.ads b/gcc/ada/libgnat/s-vallli.ads index 5bccb1a..85bf282 100644 --- a/gcc/ada/libgnat/s-vallli.ads +++ b/gcc/ada/libgnat/s-vallli.ads @@ -54,24 +54,10 @@ package System.Val_LLI with SPARK_Mode is subtype Long_Long_Unsigned is Unsigned_Types.Long_Long_Unsigned; package Impl is new Value_I - (Int => Long_Long_Integer, - Uns => Long_Long_Unsigned, - Scan_Raw_Unsigned => - Val_LLU.Scan_Raw_Long_Long_Unsigned, - Uns_Option => Val_LLU.Impl.Uns_Option, - Wrap_Option => Val_LLU.Impl.Wrap_Option, - Is_Raw_Unsigned_Format_Ghost => - Val_LLU.Impl.Is_Raw_Unsigned_Format_Ghost, - Raw_Unsigned_Overflows_Ghost => - Val_LLU.Impl.Raw_Unsigned_Overflows_Ghost, - Scan_Raw_Unsigned_Ghost => - Val_LLU.Impl.Scan_Raw_Unsigned_Ghost, - Raw_Unsigned_Last_Ghost => - Val_LLU.Impl.Raw_Unsigned_Last_Ghost, - Only_Decimal_Ghost => - Val_LLU.Impl.Only_Decimal_Ghost, - Scan_Based_Number_Ghost => - Val_LLU.Impl.Scan_Based_Number_Ghost); + (Int => Long_Long_Integer, + Uns => Long_Long_Unsigned, + Scan_Raw_Unsigned => Val_LLU.Scan_Raw_Long_Long_Unsigned, + Uns_Params => System.Val_LLU.Impl.Spec.Uns_Params); procedure Scan_Long_Long_Integer (Str : String; diff --git a/gcc/ada/libgnat/s-valllli.ads b/gcc/ada/libgnat/s-valllli.ads index 586c737..e53fb0b 100644 --- a/gcc/ada/libgnat/s-valllli.ads +++ b/gcc/ada/libgnat/s-valllli.ads @@ -54,24 +54,10 @@ package System.Val_LLLI with SPARK_Mode is subtype Long_Long_Long_Unsigned is Unsigned_Types.Long_Long_Long_Unsigned; package Impl is new Value_I - (Int => Long_Long_Long_Integer, - Uns => Long_Long_Long_Unsigned, - Scan_Raw_Unsigned => - Val_LLLU.Scan_Raw_Long_Long_Long_Unsigned, - Uns_Option => Val_LLLU.Impl.Uns_Option, - Wrap_Option => Val_LLLU.Impl.Wrap_Option, - Is_Raw_Unsigned_Format_Ghost => - Val_LLLU.Impl.Is_Raw_Unsigned_Format_Ghost, - Raw_Unsigned_Overflows_Ghost => - Val_LLLU.Impl.Raw_Unsigned_Overflows_Ghost, - Scan_Raw_Unsigned_Ghost => - Val_LLLU.Impl.Scan_Raw_Unsigned_Ghost, - Raw_Unsigned_Last_Ghost => - Val_LLLU.Impl.Raw_Unsigned_Last_Ghost, - Only_Decimal_Ghost => - Val_LLLU.Impl.Only_Decimal_Ghost, - Scan_Based_Number_Ghost => - Val_LLLU.Impl.Scan_Based_Number_Ghost); + (Int => Long_Long_Long_Integer, + Uns => Long_Long_Long_Unsigned, + Scan_Raw_Unsigned => Val_LLLU.Scan_Raw_Long_Long_Long_Unsigned, + Uns_Params => System.Val_LLLU.Impl.Spec.Uns_Params); procedure Scan_Long_Long_Long_Integer (Str : String; diff --git a/gcc/ada/libgnat/s-valuei.adb b/gcc/ada/libgnat/s-valuei.adb index b453ffc..51764b2 100644 --- a/gcc/ada/libgnat/s-valuei.adb +++ b/gcc/ada/libgnat/s-valuei.adb @@ -41,59 +41,6 @@ package body System.Value_I is Assert_And_Cut => Ignore, Subprogram_Variant => Ignore); - ----------------------------------- - -- Prove_Scan_Only_Decimal_Ghost -- - ----------------------------------- - - procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) is - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - pragma Assert - (if Val < 0 then Non_Blank = Str'First - else - Only_Space_Ghost (Str, Str'First, Str'First) - and then Non_Blank = Str'First + 1); - Minus : constant Boolean := Str (Non_Blank) = '-'; - Fst_Num : constant Positive := - (if Minus then Non_Blank + 1 else Non_Blank); - pragma Assert (Fst_Num = Str'First + 1); - Uval : constant Uns := - Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last); - - procedure Unique_Int_Of_Uns (Val1, Val2 : Int) - with - Pre => Uns_Is_Valid_Int (Minus, Uval) - and then Is_Int_Of_Uns (Minus, Uval, Val1) - and then Is_Int_Of_Uns (Minus, Uval, Val2), - Post => Val1 = Val2; - -- Local proof of the unicity of the signed representation - - procedure Unique_Int_Of_Uns (Val1, Val2 : Int) is null; - - -- Start of processing for Prove_Scan_Only_Decimal_Ghost - - begin - pragma Assert (Minus = (Val < 0)); - pragma Assert (Uval = Abs_Uns_Of_Int (Val)); - pragma Assert (if Minus then Uval <= Uns (Int'Last) + 1 - else Uval <= Uns (Int'Last)); - pragma Assert (Uns_Is_Valid_Int (Minus, Uval)); - pragma Assert - (if Minus and then Uval = Uns (Int'Last) + 1 then Val = Int'First - elsif Minus then Val = -(Int (Uval)) - else Val = Int (Uval)); - pragma Assert (Is_Int_Of_Uns (Minus, Uval, Val)); - pragma Assert - (Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))); - pragma Assert - (not Raw_Unsigned_Overflows_Ghost (Str, Fst_Num, Str'Last)); - pragma Assert (Only_Space_Ghost - (Str, Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last), Str'Last)); - pragma Assert (Is_Integer_Ghost (Str)); - pragma Assert (Is_Value_Integer_Ghost (Str, Val)); - Unique_Int_Of_Uns (Val, Value_Integer (Str)); - end Prove_Scan_Only_Decimal_Ghost; - ------------------ -- Scan_Integer -- ------------------ @@ -104,6 +51,25 @@ package body System.Value_I is Max : Integer; Res : out Int) is + procedure Prove_Is_Int_Of_Uns + (Minus : Boolean; + Uval : Uns; + Val : Int) + with Ghost, + Pre => Spec.Uns_Is_Valid_Int (Minus, Uval) + and then + (if Minus and then Uval = Uns (Int'Last) + 1 then Val = Int'First + elsif Minus then Val = -(Int (Uval)) + else Val = Int (Uval)), + Post => Spec.Is_Int_Of_Uns (Minus, Uval, Val); + -- Unfold the definition of Is_Int_Of_Uns + + procedure Prove_Is_Int_Of_Uns + (Minus : Boolean; + Uval : Uns; + Val : Int) + is null; + Uval : Uns; -- Unsigned result @@ -131,7 +97,8 @@ package body System.Value_I is end if; Scan_Raw_Unsigned (Str, Ptr, Max, Uval); - pragma Assert (Uval = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max)); + pragma Assert + (Uval = Uns_Params.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max)); -- Deal with overflow cases, and also with largest negative number @@ -152,6 +119,11 @@ package body System.Value_I is else Res := Int (Uval); end if; + + Prove_Is_Int_Of_Uns + (Minus => Str (Non_Blank) = '-', + Uval => Uval, + Val => Res); end Scan_Integer; ------------------- @@ -167,7 +139,15 @@ package body System.Value_I is if Str'Last = Positive'Last then declare subtype NT is String (1 .. Str'Length); + procedure Prove_Is_Integer_Ghost with + Ghost, + Pre => Str'Length < Natural'Last + and then not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Spec.Is_Integer_Ghost (Spec.Slide_To_1 (Str)), + Post => Spec.Is_Integer_Ghost (NT (Str)); + procedure Prove_Is_Integer_Ghost is null; begin + Prove_Is_Integer_Ghost; return Value_Integer (NT (Str)); end; @@ -187,8 +167,6 @@ package body System.Value_I is else Non_Blank) with Ghost; begin - pragma Assert - (Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))); declare P_Acc : constant not null access Integer := P'Access; @@ -197,12 +175,13 @@ package body System.Value_I is end; pragma Assert - (P = Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last)); + (P = Uns_Params.Raw_Unsigned_Last_Ghost + (Str, Fst_Num, Str'Last)); Scan_Trailing_Blanks (Str, P); pragma Assert - (Is_Value_Integer_Ghost (Slide_If_Necessary (Str), V)); + (Spec.Is_Value_Integer_Ghost (Spec.Slide_If_Necessary (Str), V)); return V; end; end if; diff --git a/gcc/ada/libgnat/s-valuei.ads b/gcc/ada/libgnat/s-valuei.ads index 5e42773..3f78db6 100644 --- a/gcc/ada/libgnat/s-valuei.ads +++ b/gcc/ada/libgnat/s-valuei.ads @@ -39,6 +39,7 @@ pragma Assertion_Policy (Pre => Ignore, Subprogram_Variant => Ignore); with System.Val_Util; use System.Val_Util; +with System.Value_I_Spec; generic @@ -54,71 +55,15 @@ generic -- Additional parameters for ghost subprograms used inside contracts - type Uns_Option is private; - with function Wrap_Option (Value : Uns) return Uns_Option - with Ghost; - with function Is_Raw_Unsigned_Format_Ghost (Str : String) return Boolean - with Ghost; - with function Raw_Unsigned_Overflows_Ghost - (Str : String; - From, To : Integer) - return Boolean - with Ghost; - with function Scan_Raw_Unsigned_Ghost - (Str : String; - From, To : Integer) - return Uns - with Ghost; - with function Raw_Unsigned_Last_Ghost - (Str : String; - From, To : Integer) - return Positive - with Ghost; - with function Only_Decimal_Ghost - (Str : String; - From, To : Integer) - return Boolean - with Ghost; - with function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - return Uns_Option - with Ghost; + with package Uns_Params is new System.Val_Util.Uns_Params + (Uns => Uns, others => <>) + with Ghost; package System.Value_I is pragma Preelaborate; + use all type Uns_Params.Uns_Option; - function Uns_Is_Valid_Int (Minus : Boolean; Uval : Uns) return Boolean is - (if Minus then Uval <= Uns (Int'Last) + 1 - else Uval <= Uns (Int'Last)) - with Ghost, - Post => True; - -- Return True if Uval (or -Uval when Minus is True) is a valid number of - -- type Int. - - function Is_Int_Of_Uns - (Minus : Boolean; - Uval : Uns; - Val : Int) - return Boolean - is - (if Minus and then Uval = Uns (Int'Last) + 1 then Val = Int'First - elsif Minus then Val = -(Int (Uval)) - else Val = Int (Uval)) - with - Ghost, - Pre => Uns_Is_Valid_Int (Minus, Uval), - Post => True; - -- Return True if Uval (or -Uval when Minus is True) is equal to Val - - function Abs_Uns_Of_Int (Val : Int) return Uns is - (if Val = Int'First then Uns (Int'Last) + 1 - elsif Val < 0 then Uns (-Val) - else Uns (Val)) - with Ghost; - -- Return the unsigned absolute value of Val + package Spec is new System.Value_I_Spec (Int, Uns, Uns_Params); procedure Scan_Integer (Str : String; @@ -139,11 +84,13 @@ package System.Value_I is (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); begin - Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Max)) - and then not Raw_Unsigned_Overflows_Ghost (Str, Fst_Num, Max) - and then Uns_Is_Valid_Int + Uns_Params.Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Max)) + and then Uns_Params.Raw_Unsigned_No_Overflow_Ghost + (Str, Fst_Num, Max) + and then Spec.Uns_Is_Valid_Int (Minus => Str (Non_Blank) = '-', - Uval => Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max))), + Uval => Uns_Params.Scan_Raw_Unsigned_Ghost + (Str, Fst_Num, Max))), Post => (declare Non_Blank : constant Positive := First_Non_Space_Ghost @@ -152,12 +99,13 @@ package System.Value_I is (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); Uval : constant Uns := - Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max); + Uns_Params.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max); begin - Is_Int_Of_Uns (Minus => Str (Non_Blank) = '-', - Uval => Uval, - Val => Res) - and then Ptr.all = Raw_Unsigned_Last_Ghost (Str, Fst_Num, Max)); + Spec.Is_Int_Of_Uns (Minus => Str (Non_Blank) = '-', + Uval => Uval, + Val => Res) + and then Ptr.all = Uns_Params.Raw_Unsigned_Last_Ghost + (Str, Fst_Num, Max)); -- This procedure scans the string starting at Str (Ptr.all) for a valid -- integer according to the syntax described in (RM 3.5(43)). The substring -- scanned extends no further than Str (Max). There are three cases for the @@ -183,111 +131,17 @@ package System.Value_I is -- special case of an all-blank string, and Ptr is unchanged, and hence -- is greater than Max as required in this case. - function Slide_To_1 (Str : String) return String - with - Ghost, - Post => - Only_Space_Ghost (Str, Str'First, Str'Last) = - (for all J in Str'First .. Str'Last => - Slide_To_1'Result (J - Str'First + 1) = ' '); - -- Slides Str so that it starts at 1 - - function Slide_If_Necessary (Str : String) return String is - (if Str'Last = Positive'Last then Slide_To_1 (Str) else Str) - with - Ghost, - Post => - Only_Space_Ghost (Str, Str'First, Str'Last) = - Only_Space_Ghost (Slide_If_Necessary'Result, - Slide_If_Necessary'Result'First, - Slide_If_Necessary'Result'Last); - -- If Str'Last = Positive'Last then slides Str so that it starts at 1 - - function Is_Integer_Ghost (Str : String) return Boolean is - (declare - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - Fst_Num : constant Positive := - (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); - begin - Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last)) - and then not Raw_Unsigned_Overflows_Ghost (Str, Fst_Num, Str'Last) - and then - Uns_Is_Valid_Int - (Minus => Str (Non_Blank) = '-', - Uval => Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last)) - and then Only_Space_Ghost - (Str, Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last), Str'Last)) - with - Ghost, - Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) - and then Str'Last /= Positive'Last, - Post => True; - -- Ghost function that determines if Str has the correct format for a - -- signed number, consisting in some blank characters, an optional - -- sign, a raw unsigned number which does not overflow and then some - -- more blank characters. - - function Is_Value_Integer_Ghost (Str : String; Val : Int) return Boolean is - (declare - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - Fst_Num : constant Positive := - (if Str (Non_Blank) in '+' | '-' then Non_Blank + 1 else Non_Blank); - Uval : constant Uns := - Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last); - begin - Is_Int_Of_Uns (Minus => Str (Non_Blank) = '-', - Uval => Uval, - Val => Val)) - with - Ghost, - Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) - and then Str'Last /= Positive'Last - and then Is_Integer_Ghost (Str), - Post => True; - -- Ghost function that returns True if Val is the value corresponding to - -- the signed number represented by Str. - function Value_Integer (Str : String) return Int with Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) and then Str'Length /= Positive'Last - and then Is_Integer_Ghost (Slide_If_Necessary (Str)), - Post => Is_Value_Integer_Ghost - (Slide_If_Necessary (Str), Value_Integer'Result), + and then Spec.Is_Integer_Ghost (Spec.Slide_If_Necessary (Str)), + Post => Spec.Is_Value_Integer_Ghost + (Spec.Slide_If_Necessary (Str), Value_Integer'Result), Subprogram_Variant => (Decreases => Str'First); -- Used in computing X'Value (Str) where X is a signed integer type whose -- base range does not exceed the base range of Integer. Str is the string -- argument of the attribute. Constraint_Error is raised if the string is -- malformed, or if the value is out of range. - procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) - with - Ghost, - Pre => Str'Last /= Positive'Last - and then Str'Length >= 2 - and then Str (Str'First) in ' ' | '-' - and then (Str (Str'First) = '-') = (Val < 0) - and then Only_Decimal_Ghost (Str, Str'First + 1, Str'Last) - and then Scan_Based_Number_Ghost (Str, Str'First + 1, Str'Last) - = Wrap_Option (Abs_Uns_Of_Int (Val)), - Post => Is_Integer_Ghost (Slide_If_Necessary (Str)) - and then Value_Integer (Str) = Val; - -- Ghost lemma used in the proof of 'Image implementation, to prove that - -- the result of Value_Integer on a decimal string is the same as the - -- signing the result of Scan_Based_Number_Ghost. - -private - - ---------------- - -- Slide_To_1 -- - ---------------- - - function Slide_To_1 (Str : String) return String is - (declare - Res : constant String (1 .. Str'Length) := Str; - begin - Res); - end System.Value_I; diff --git a/gcc/ada/libgnat/s-valuer.adb b/gcc/ada/libgnat/s-valuer.adb index b474f84..fc91660 100644 --- a/gcc/ada/libgnat/s-valuer.adb +++ b/gcc/ada/libgnat/s-valuer.adb @@ -184,7 +184,7 @@ package body System.Value_R is UmaxB : constant Uns := Precision_Limit / Uns (Base); -- Numbers bigger than UmaxB overflow if multiplied by base - Precision_Limit_Reached : Boolean := False; + Precision_Limit_Reached : Boolean; -- Set to True if addition of a digit will cause Value to be superior -- to Precision_Limit. @@ -198,7 +198,7 @@ package body System.Value_R is Temp : Uns; -- Temporary - Trailing_Zeros : Natural := 0; + Trailing_Zeros : Natural; -- Number of trailing zeros at a given point begin @@ -209,12 +209,17 @@ package body System.Value_R is Precision_Limit_Reached := True; else Extra := 0; + Precision_Limit_Reached := False; end if; if Round then Precision_Limit_Just_Reached := False; end if; + -- Initialize trailing zero counter + + Trailing_Zeros := 0; + -- The function precondition is that the first character is a valid -- digit. @@ -362,7 +367,7 @@ package body System.Value_R is UmaxB : constant Uns := Precision_Limit / Uns (Base); -- Numbers bigger than UmaxB overflow if multiplied by base - Precision_Limit_Reached : Boolean := False; + Precision_Limit_Reached : Boolean; -- Set to True if addition of a digit will cause Value to be superior -- to Precision_Limit. @@ -383,6 +388,8 @@ package body System.Value_R is Scale := 0; Extra := 0; + Precision_Limit_Reached := False; + if Round then Precision_Limit_Just_Reached := False; end if; @@ -494,28 +501,32 @@ package body System.Value_R is After_Point : Boolean; -- True if a decimal should be parsed - Base_Char : Character := ASCII.NUL; - -- Character used to set the base. If Nul this means that default + Base_Char : Character; + -- Character used to set the base. If it is Nul, this means that default -- base is used. - Base_Violation : Boolean := False; + Base_Violation : Boolean; -- If True some digits where not in the base. The real is still scanned -- till the end even if an error will be raised. + Expon : Integer; + -- Exponent as an Integer + Index : Integer; -- Local copy of string pointer Start : Positive; + -- Index of the first non-blank character Value : Uns; -- Mantissa as an Integer - Expon : Integer; - begin -- The default base is 10 - Base := 10; + Base := 10; + Base_Char := ASCII.NUL; + Base_Violation := False; -- We do not tolerate strings with Str'Last = Positive'Last diff --git a/gcc/ada/libgnat/s-valueu.adb b/gcc/ada/libgnat/s-valueu.adb index f5a6881..8f19086 100644 --- a/gcc/ada/libgnat/s-valueu.adb +++ b/gcc/ada/libgnat/s-valueu.adb @@ -41,9 +41,12 @@ package body System.Value_U is Assert_And_Cut => Ignore, Subprogram_Variant => Ignore); + use type Spec.Uns_Option; + use type Spec.Split_Value_Ghost; + -- Local lemmas - procedure Lemma_Digit_Is_Before_Last + procedure Lemma_Digit_Not_Last (Str : String; P : Integer; From : Integer; @@ -54,257 +57,47 @@ package body System.Value_U is and then To in From .. Str'Last and then Str (From) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' and then P in From .. To - and then Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F', - Post => P /= Last_Hexa_Ghost (Str (From .. To)) + 1; - -- If the character at position P is a digit, P cannot be the position of - -- of the first non-digit in Str. + and then P <= Spec.Last_Hexa_Ghost (Str (From .. To)) + 1 + and then Spec.Is_Based_Format_Ghost (Str (From .. To)), + Post => + (if Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' + then P <= Spec.Last_Hexa_Ghost (Str (From .. To))); - procedure Lemma_End_Of_Scan + procedure Lemma_Underscore_Not_Last (Str : String; + P : Integer; From : Integer; - To : Integer; - Base : Uns; - Acc : Uns) - with Ghost, - Pre => Str'Last /= Positive'Last and then From > To, - Post => Scan_Based_Number_Ghost (Str, From, To, Base, Acc) = - (False, Acc); - -- Unfold the definition of Scan_Based_Number_Ghost on an empty string - - procedure Lemma_Scan_Digit - (Str : String; - P : Integer; - Lst : Integer; - Digit : Uns; - Base : Uns; - Old_Acc : Uns; - Acc : Uns; - Scan_Val : Uns_Option; - Old_Overflow : Boolean; - Overflow : Boolean) - with Ghost, - Pre => Str'Last /= Positive'Last - and then Lst in Str'Range - and then P in Str'First .. Lst - and then Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' - and then Digit = Hexa_To_Unsigned_Ghost (Str (P)) - and then Only_Hexa_Ghost (Str, P, Lst) - and then Base in 2 .. 16 - and then (if Digit < Base and then Old_Acc <= Uns'Last / Base - then Acc = Base * Old_Acc + Digit) - and then (if Digit >= Base - or else Old_Acc > Uns'Last / Base - or else (Old_Acc > (Uns'Last - Base + 1) / Base - and then Acc < Uns'Last / Base) - then Overflow - else Overflow = Old_Overflow) - and then - (if not Old_Overflow then - Scan_Val = Scan_Based_Number_Ghost - (Str, P, Lst, Base, Old_Acc)), - Post => - (if not Overflow then - Scan_Val = Scan_Based_Number_Ghost - (Str, P + 1, Lst, Base, Acc)) - and then - (if Overflow then Old_Overflow or else Scan_Val.Overflow); - -- Unfold the definition of Scan_Based_Number_Ghost when the string starts - -- with a digit. - - procedure Lemma_Scan_Underscore - (Str : String; - P : Integer; - From : Integer; - To : Integer; - Lst : Integer; - Base : Uns; - Acc : Uns; - Scan_Val : Uns_Option; - Overflow : Boolean; - Ext : Boolean) + To : Integer) with Ghost, Pre => Str'Last /= Positive'Last and then From in Str'Range and then To in From .. Str'Last - and then Lst <= To - and then P in From .. Lst + 1 - and then P <= To - and then - (if Ext then - Is_Based_Format_Ghost (Str (From .. To)) - and then Lst = Last_Hexa_Ghost (Str (From .. To)) - else Is_Natural_Format_Ghost (Str (From .. To)) - and then Lst = Last_Number_Ghost (Str (From .. To))) + and then Str (From) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' + and then P in From .. To and then Str (P) = '_' - and then - (if not Overflow then - Scan_Val = Scan_Based_Number_Ghost (Str, P, Lst, Base, Acc)), - Post => P + 1 <= Lst - and then - (if Ext then Str (P + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' - else Str (P + 1) in '0' .. '9') - and then - (if not Overflow then - Scan_Val = Scan_Based_Number_Ghost (Str, P + 1, Lst, Base, Acc)); - -- Unfold the definition of Scan_Based_Number_Ghost when the string starts - -- with an underscore. + and then P <= Spec.Last_Hexa_Ghost (Str (From .. To)) + 1 + and then Spec.Is_Based_Format_Ghost (Str (From .. To)), + Post => P + 1 <= Spec.Last_Hexa_Ghost (Str (From .. To)) + and then Str (P + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; ----------------------------- -- Local lemma null bodies -- ----------------------------- - procedure Lemma_Digit_Is_Before_Last + procedure Lemma_Digit_Not_Last (Str : String; P : Integer; From : Integer; To : Integer) is null; - procedure Lemma_End_Of_Scan - (Str : String; - From : Integer; - To : Integer; - Base : Uns; - Acc : Uns) - is null; - - procedure Lemma_Scan_Underscore - (Str : String; - P : Integer; - From : Integer; - To : Integer; - Lst : Integer; - Base : Uns; - Acc : Uns; - Scan_Val : Uns_Option; - Overflow : Boolean; - Ext : Boolean) + procedure Lemma_Underscore_Not_Last + (Str : String; + P : Integer; + From : Integer; + To : Integer) is null; - --------------------- - -- Last_Hexa_Ghost -- - --------------------- - - function Last_Hexa_Ghost (Str : String) return Positive is - begin - for J in Str'Range loop - if Str (J) not in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_' then - return J - 1; - end if; - - pragma Loop_Invariant - (for all K in Str'First .. J => - Str (K) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'); - end loop; - - return Str'Last; - end Last_Hexa_Ghost; - - ---------------------- - -- Lemma_Scan_Digit -- - ---------------------- - - procedure Lemma_Scan_Digit - (Str : String; - P : Integer; - Lst : Integer; - Digit : Uns; - Base : Uns; - Old_Acc : Uns; - Acc : Uns; - Scan_Val : Uns_Option; - Old_Overflow : Boolean; - Overflow : Boolean) - is - pragma Unreferenced (Str, P, Lst, Scan_Val, Overflow, Old_Overflow); - begin - if Digit >= Base then - null; - - elsif Old_Acc <= (Uns'Last - Base + 1) / Base then - pragma Assert (not Scan_Overflows_Ghost (Digit, Base, Old_Acc)); - - elsif Old_Acc > Uns'Last / Base then - null; - - else - pragma Assert - ((Acc < Uns'Last / Base) = - Scan_Overflows_Ghost (Digit, Base, Old_Acc)); - end if; - end Lemma_Scan_Digit; - - ---------------------------------------- - -- Prove_Iter_Scan_Based_Number_Ghost -- - ---------------------------------------- - - procedure Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - is - begin - if From > To then - null; - elsif Str1 (From) = '_' then - Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2, From + 1, To, Base, Acc); - elsif Scan_Overflows_Ghost - (Hexa_To_Unsigned_Ghost (Str1 (From)), Base, Acc) - then - null; - else - Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2, From + 1, To, Base, - Base * Acc + Hexa_To_Unsigned_Ghost (Str1 (From))); - end if; - end Prove_Iter_Scan_Based_Number_Ghost; - - ----------------------------------- - -- Prove_Scan_Only_Decimal_Ghost -- - ----------------------------------- - - procedure Prove_Scan_Only_Decimal_Ghost - (Str : String; - Val : Uns) - is - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - pragma Assert (Non_Blank = Str'First + 1); - Fst_Num : constant Positive := - (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); - pragma Assert (Fst_Num = Str'First + 1); - Last_Num_Init : constant Integer := - Last_Number_Ghost (Str (Str'First + 1 .. Str'Last)); - pragma Assert (Last_Num_Init = Str'Last); - Starts_As_Based : constant Boolean := - Last_Num_Init < Str'Last - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Str (Last_Num_Init + 2) in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - pragma Assert (Starts_As_Based = False); - Last_Num_Based : constant Integer := - (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Str'Last)) - else Last_Num_Init); - pragma Assert (Last_Num_Based = Str'Last); - begin - pragma Assert - (Is_Opt_Exponent_Format_Ghost (Str (Str'Last + 1 .. Str'Last))); - pragma Assert - (Is_Natural_Format_Ghost (Str (Str'First + 1 .. Str'Last))); - pragma Assert - (Is_Raw_Unsigned_Format_Ghost (Str (Str'First + 1 .. Str'Last))); - pragma Assert - (not Raw_Unsigned_Overflows_Ghost (Str, Str'First + 1, Str'Last)); - pragma Assert (Val = Exponent_Unsigned_Ghost (Val, 0, 10).Value); - pragma Assert - (Val = Scan_Raw_Unsigned_Ghost (Str, Str'First + 1, Str'Last)); - pragma Assert (Is_Unsigned_Ghost (Str)); - pragma Assert (Is_Value_Unsigned_Ghost (Str, Val)); - end Prove_Scan_Only_Decimal_Ghost; - ----------------------- -- Scan_Raw_Unsigned -- ----------------------- @@ -341,8 +134,8 @@ package body System.Value_U is Last_Num_Init : constant Integer := Last_Number_Ghost (Str (Ptr.all .. Max)) with Ghost; - Init_Val : constant Uns_Option := - Scan_Based_Number_Ghost (Str, Ptr.all, Last_Num_Init) + Init_Val : constant Spec.Uns_Option := + Spec.Scan_Based_Number_Ghost (Str, Ptr.all, Last_Num_Init) with Ghost; Starts_As_Based : constant Boolean := Last_Num_Init < Max - 1 @@ -352,7 +145,7 @@ package body System.Value_U is with Ghost; Last_Num_Based : constant Integer := (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Max)) + then Spec.Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Max)) else Last_Num_Init) with Ghost; Is_Based : constant Boolean := @@ -360,9 +153,9 @@ package body System.Value_U is and then Last_Num_Based < Max and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1) with Ghost; - Based_Val : constant Uns_Option := + Based_Val : constant Spec.Uns_Option := (if Starts_As_Based and then not Init_Val.Overflow - then Scan_Based_Number_Ghost + then Spec.Scan_Based_Number_Ghost (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value) else Init_Val) with Ghost; @@ -379,6 +172,7 @@ package body System.Value_U is end if; P := Ptr.all; + Spec.Lemma_Scan_Based_Number_Ghost_Step (Str, P, Last_Num_Init); Uval := Character'Pos (Str (P)) - Character'Pos ('0'); P := P + 1; @@ -392,9 +186,6 @@ package body System.Value_U is Umax10 : constant Uns := Uns'Last / 10; -- Numbers bigger than Umax10 overflow if multiplied by 10 - Old_Uval : Uns with Ghost; - Old_Overflow : Boolean with Ghost; - begin -- Loop through decimal digits loop @@ -403,7 +194,7 @@ package body System.Value_U is (if Overflow then Init_Val.Overflow); pragma Loop_Invariant (if not Overflow - then Init_Val = Scan_Based_Number_Ghost + then Init_Val = Spec.Scan_Based_Number_Ghost (Str, P, Last_Num_Init, Acc => Uval)); exit when P > Max; @@ -414,9 +205,8 @@ package body System.Value_U is if Digit > 9 then if Str (P) = '_' then - Lemma_Scan_Underscore - (Str, P, Ptr_Old, Max, Last_Num_Init, 10, Uval, - Init_Val, Overflow, False); + Spec.Lemma_Scan_Based_Number_Ghost_Underscore + (Str, P, Last_Num_Init, Acc => Uval); Scan_Underscore (Str, P, Ptr, Max, False); else exit; @@ -425,11 +215,19 @@ package body System.Value_U is -- Accumulate result, checking for overflow else - Old_Uval := Uval; - Old_Overflow := Overflow; + Spec.Lemma_Scan_Based_Number_Ghost_Step + (Str, P, Last_Num_Init, Acc => Uval); + Spec.Lemma_Scan_Based_Number_Ghost_Overflow + (Str, P, Last_Num_Init, Acc => Uval); if Uval <= Umax then + pragma Assert + (Spec.Hexa_To_Unsigned_Ghost (Str (P)) = Digit); Uval := 10 * Uval + Digit; + pragma Assert + (if not Overflow + then Init_Val = Spec.Scan_Based_Number_Ghost + (Str, P + 1, Last_Num_Init, Acc => Uval)); elsif Uval > Umax10 then Overflow := True; @@ -440,17 +238,17 @@ package body System.Value_U is if Uval < Umax10 then Overflow := True; end if; + pragma Assert + (if not Overflow + then Init_Val = Spec.Scan_Based_Number_Ghost + (Str, P + 1, Last_Num_Init, Acc => Uval)); end if; - Lemma_Scan_Digit - (Str, P, Last_Num_Init, Digit, 10, Old_Uval, Uval, Init_Val, - Old_Overflow, Overflow); - P := P + 1; end if; end loop; - pragma Assert (P = Last_Num_Init + 1); - pragma Assert (Init_Val.Overflow = Overflow); + Spec.Lemma_Scan_Based_Number_Ghost_Base + (Str, P, Last_Num_Init, Acc => Uval); end; pragma Assert_And_Cut @@ -488,18 +286,14 @@ package body System.Value_U is UmaxB : constant Uns := Uns'Last / Base; -- Numbers bigger than UmaxB overflow if multiplied by base - Old_Uval : Uns with Ghost; - Old_Overflow : Boolean with Ghost; - begin pragma Assert (if Str (P) in '0' .. '9' | 'A' .. 'F' | 'a' .. 'f' - then Is_Based_Format_Ghost (Str (P .. Max))); + then Spec.Is_Based_Format_Ghost (Str (P .. Max))); -- Loop to scan out based integer value loop - -- We require a digit at this stage if Str (P) in '0' .. '9' then @@ -519,6 +313,8 @@ package body System.Value_U is -- already stored in Ptr.all. else + Spec.Lemma_Scan_Based_Number_Ghost_Base + (Str, P, Last_Num_Based, Base, Uval); Uval := Base; Base := 10; pragma Assert (Ptr.all = Last_Num_Init + 1); @@ -529,25 +325,25 @@ package body System.Value_U is exit; end if; - Lemma_Digit_Is_Before_Last (Str, P, Last_Num_Init + 2, Max); - pragma Loop_Invariant (P in P'Loop_Entry .. Last_Num_Based); pragma Loop_Invariant (Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' - and then Digit = Hexa_To_Unsigned_Ghost (Str (P))); + and then Digit = Spec.Hexa_To_Unsigned_Ghost (Str (P))); pragma Loop_Invariant (if Overflow'Loop_Entry then Overflow); pragma Loop_Invariant (if Overflow then - Overflow'Loop_Entry or else Based_Val.Overflow); + (Overflow'Loop_Entry or else Based_Val.Overflow)); pragma Loop_Invariant (if not Overflow - then Based_Val = Scan_Based_Number_Ghost + then Based_Val = Spec.Scan_Based_Number_Ghost (Str, P, Last_Num_Based, Base, Uval)); pragma Loop_Invariant (Ptr.all = Last_Num_Init + 1); - Old_Uval := Uval; - Old_Overflow := Overflow; + Spec.Lemma_Scan_Based_Number_Ghost_Step + (Str, P, Last_Num_Based, Base, Uval); + Spec.Lemma_Scan_Based_Number_Ghost_Overflow + (Str, P, Last_Num_Based, Base, Uval); -- If digit is too large, just signal overflow and continue. -- The idea here is to keep scanning as long as the input is @@ -560,6 +356,10 @@ package body System.Value_U is elsif Uval <= Umax then Uval := Base * Uval + Digit; + pragma Assert + (if not Overflow + then Based_Val = Spec.Scan_Based_Number_Ghost + (Str, P + 1, Last_Num_Based, Base, Uval)); elsif Uval > UmaxB then Overflow := True; @@ -570,6 +370,10 @@ package body System.Value_U is if Uval < UmaxB then Overflow := True; end if; + pragma Assert + (if not Overflow + then Based_Val = Spec.Scan_Based_Number_Ghost + (Str, P + 1, Last_Num_Based, Base, Uval)); end if; -- If at end of string with no base char, not a based number @@ -579,10 +383,6 @@ package body System.Value_U is P := P + 1; - Lemma_Scan_Digit - (Str, P - 1, Last_Num_Based, Digit, Base, Old_Uval, Uval, - Based_Val, Old_Overflow, Overflow); - if P > Max then Ptr.all := P; Bad_Value (Str); @@ -592,48 +392,54 @@ package body System.Value_U is if Str (P) = Base_Char then Ptr.all := P + 1; + pragma Assert (P = Last_Num_Based + 1); pragma Assert (Ptr.all = Last_Num_Based + 2); + pragma Assert (Starts_As_Based); + pragma Assert (Last_Num_Based < Max); + pragma Assert (Str (Last_Num_Based + 1) = Base_Char); + pragma Assert (Base_Char = Str (Last_Num_Init + 1)); pragma Assert (Is_Based); - pragma Assert - (if not Overflow then - Based_Val = Scan_Based_Number_Ghost - (Str, P, Last_Num_Based, Base, Uval)); - Lemma_End_Of_Scan (Str, P, Last_Num_Based, Base, Uval); - pragma Assert (if not Overflow then Uval = Based_Val.Value); + Spec.Lemma_Scan_Based_Number_Ghost_Base + (Str, P, Last_Num_Based, Base, Uval); exit; -- Deal with underscore elsif Str (P) = '_' then - Lemma_Scan_Underscore - (Str, P, Last_Num_Init + 2, Max, Last_Num_Based, Base, - Uval, Based_Val, Overflow, True); + Lemma_Underscore_Not_Last (Str, P, Last_Num_Init + 2, Max); + Spec.Lemma_Scan_Based_Number_Ghost_Underscore + (Str, P, Last_Num_Based, Base, Uval); Scan_Underscore (Str, P, Ptr, Max, True); pragma Assert (if not Overflow - then Based_Val = Scan_Based_Number_Ghost + then Based_Val = Spec.Scan_Based_Number_Ghost (Str, P, Last_Num_Based, Base, Uval)); + pragma Assert (Str (P) /= '_'); + pragma Assert (Str (P) /= Base_Char); end if; + + Lemma_Digit_Not_Last (Str, P, Last_Num_Init + 2, Max); + pragma Assert (Str (P) /= '_'); + pragma Assert (Str (P) /= Base_Char); end loop; end; pragma Assert (if Starts_As_Based then P = Last_Num_Based + 1 else P = Last_Num_Init + 2); pragma Assert + (Last_Num_Init < Max - 1 + and then Str (Last_Num_Init + 1) in '#' | ':'); + pragma Assert (Overflow = (Init_Val.Overflow or else Init_Val.Value not in 2 .. 16 or else (Starts_As_Based and then Based_Val.Overflow))); + pragma Assert + (Overflow /= Spec.Scan_Split_No_Overflow_Ghost (Str, Ptr_Old, Max)); end if; pragma Assert_And_Cut - (Overflow = - (Init_Val.Overflow - or else - (Last_Num_Init < Max - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Init_Val.Value not in 2 .. 16) - or else (Starts_As_Based and then Based_Val.Overflow)) + (Overflow /= Spec.Scan_Split_No_Overflow_Ghost (Str, Ptr_Old, Max) and then (if not Overflow then (if Is_Based then Uval = Based_Val.Value @@ -649,10 +455,12 @@ package body System.Value_U is Scan_Exponent (Str, Ptr, Max, Expon); - pragma Assert (Ptr.all = Raw_Unsigned_Last_Ghost (Str, Ptr_Old, Max)); pragma Assert - (if Starts_As_Exponent_Format_Ghost (Str (First_Exp .. Max)) - then Expon = Scan_Exponent_Ghost (Str (First_Exp .. Max))); + (Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Ptr_Old, Max)); + pragma Assert + (if not Overflow + then Spec.Scan_Split_Value_Ghost (Str, Ptr_Old, Max) = + (Uval, Base, Expon)); if Expon /= 0 and then Uval /= 0 then @@ -664,8 +472,8 @@ package body System.Value_U is UmaxB : constant Uns := Uns'Last / Base; -- Numbers bigger than UmaxB overflow if multiplied by base - Res_Val : constant Uns_Option := - Exponent_Unsigned_Ghost (Uval, Expon, Base) + Res_Val : constant Spec.Uns_Option := + Spec.Exponent_Unsigned_Ghost (Uval, Expon, Base) with Ghost; begin for J in 1 .. Expon loop @@ -674,48 +482,45 @@ package body System.Value_U is pragma Loop_Invariant (if Overflow then Overflow'Loop_Entry or else Res_Val.Overflow); + pragma Loop_Invariant (Uval /= 0); pragma Loop_Invariant (if not Overflow - then Res_Val = Exponent_Unsigned_Ghost + then Res_Val = Spec.Exponent_Unsigned_Ghost (Uval, Expon - J + 1, Base)); pragma Assert - ((Uval > UmaxB) = Scan_Overflows_Ghost (0, Base, Uval)); + ((Uval > UmaxB) = Spec.Scan_Overflows_Ghost (0, Base, Uval)); if Uval > UmaxB then + Spec.Lemma_Exponent_Unsigned_Ghost_Overflow + (Uval, Expon - J + 1, Base); Overflow := True; exit; end if; + Spec.Lemma_Exponent_Unsigned_Ghost_Step + (Uval, Expon - J + 1, Base); + Uval := Uval * Base; end loop; + Spec.Lemma_Exponent_Unsigned_Ghost_Base (Uval, 0, Base); + pragma Assert - (Overflow = (Init_Val.Overflow - or else - (Last_Num_Init < Max - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Init_Val.Value not in 2 .. 16) - or else (Starts_As_Based and then Based_Val.Overflow) - or else Res_Val.Overflow)); - pragma Assert - (Overflow = Raw_Unsigned_Overflows_Ghost (Str, Ptr_Old, Max)); - pragma Assert - (Exponent_Unsigned_Ghost (Uval, 0, Base) = (False, Uval)); - pragma Assert - (if not Overflow then Uval = Res_Val.Value); - pragma Assert - (if not Overflow then - Uval = Scan_Raw_Unsigned_Ghost (Str, Ptr_Old, Max)); + (Overflow /= + Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr_Old, Max)); + pragma Assert (if not Overflow then Res_Val = (False, Uval)); end; end if; + Spec.Lemma_Exponent_Unsigned_Ghost_Base (Uval, Expon, Base); pragma Assert (if Expon = 0 or else Uval = 0 then - Exponent_Unsigned_Ghost (Uval, Expon, Base) = (False, Uval)); + Spec.Exponent_Unsigned_Ghost (Uval, Expon, Base) = (False, Uval)); pragma Assert - (Overflow = Raw_Unsigned_Overflows_Ghost (Str, Ptr_Old, Max)); + (Overflow /= + Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr_Old, Max)); pragma Assert (if not Overflow then - Uval = Scan_Raw_Unsigned_Ghost (Str, Ptr_Old, Max)); + Uval = Spec.Scan_Raw_Unsigned_Ghost (Str, Ptr_Old, Max)); -- Return result, dealing with overflow @@ -774,7 +579,15 @@ package body System.Value_U is if Str'Last = Positive'Last then declare subtype NT is String (1 .. Str'Length); + procedure Prove_Is_Unsigned_Ghost with + Ghost, + Pre => Str'Length < Natural'Last + and then not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Spec.Is_Unsigned_Ghost (Spec.Slide_To_1 (Str)), + Post => Spec.Is_Unsigned_Ghost (NT (Str)); + procedure Prove_Is_Unsigned_Ghost is null; begin + Prove_Is_Unsigned_Ghost; return Value_Unsigned (NT (Str)); end; @@ -784,7 +597,6 @@ package body System.Value_U is declare V : Uns; P : aliased Integer := Str'First; - Non_Blank : constant Positive := First_Non_Space_Ghost (Str, Str'First, Str'Last) with Ghost; @@ -792,9 +604,6 @@ package body System.Value_U is (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank) with Ghost; begin - pragma Assert - (Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))); - declare P_Acc : constant not null access Integer := P'Access; begin @@ -802,14 +611,15 @@ package body System.Value_U is end; pragma Assert - (P = Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last)); + (P = Spec.Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last)); pragma Assert - (V = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last)); + (V = Spec.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last)); Scan_Trailing_Blanks (Str, P); pragma Assert - (Is_Value_Unsigned_Ghost (Slide_If_Necessary (Str), V)); + (Spec.Is_Value_Unsigned_Ghost + (Spec.Slide_If_Necessary (Str), V)); return V; end; end if; diff --git a/gcc/ada/libgnat/s-valueu.ads b/gcc/ada/libgnat/s-valueu.ads index 1508b6e..466b96a 100644 --- a/gcc/ada/libgnat/s-valueu.ads +++ b/gcc/ada/libgnat/s-valueu.ads @@ -44,6 +44,7 @@ pragma Assertion_Policy (Pre => Ignore, Ghost => Ignore, Subprogram_Variant => Ignore); +with System.Value_U_Spec; with System.Val_Util; use System.Val_Util; generic @@ -53,317 +54,7 @@ generic package System.Value_U is pragma Preelaborate; - type Uns_Option (Overflow : Boolean := False) is record - case Overflow is - when True => - null; - when False => - Value : Uns := 0; - end case; - end record; - - function Wrap_Option (Value : Uns) return Uns_Option is - (Overflow => False, Value => Value) - with - Ghost; - - function Only_Decimal_Ghost - (Str : String; - From, To : Integer) - return Boolean - is - (for all J in From .. To => Str (J) in '0' .. '9') - with - Ghost, - Pre => From > To or else (From >= Str'First and then To <= Str'Last); - -- Ghost function that returns True if S has only decimal characters - -- from index From to index To. - - function Only_Hexa_Ghost (Str : String; From, To : Integer) return Boolean - is - (for all J in From .. To => - Str (J) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_') - with - Ghost, - Pre => From > To or else (From >= Str'First and then To <= Str'Last); - -- Ghost function that returns True if S has only hexadecimal characters - -- from index From to index To. - - function Last_Hexa_Ghost (Str : String) return Positive - with - Ghost, - Pre => Str /= "" - and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F', - Post => Last_Hexa_Ghost'Result in Str'Range - and then (if Last_Hexa_Ghost'Result < Str'Last then - Str (Last_Hexa_Ghost'Result + 1) not in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_') - and then Only_Hexa_Ghost (Str, Str'First, Last_Hexa_Ghost'Result); - -- Ghost function that returns the index of the last character in S that - -- is either an hexadecimal digit or an underscore, which necessarily - -- exists given the precondition on Str. - - function Is_Based_Format_Ghost (Str : String) return Boolean - is - (Str /= "" - and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' - and then - (declare - L : constant Positive := Last_Hexa_Ghost (Str); - begin - Str (L) /= '_' - and then (for all J in Str'First .. L => - (if Str (J) = '_' then Str (J + 1) /= '_')))) - with - Ghost; - -- Ghost function that determines if Str has the correct format for a - -- based number, consisting in a sequence of hexadecimal digits possibly - -- separated by single underscores. It may be followed by other characters. - - function Hexa_To_Unsigned_Ghost (X : Character) return Uns is - (case X is - when '0' .. '9' => Character'Pos (X) - Character'Pos ('0'), - when 'a' .. 'f' => Character'Pos (X) - Character'Pos ('a') + 10, - when 'A' .. 'F' => Character'Pos (X) - Character'Pos ('A') + 10, - when others => raise Program_Error) - with - Ghost, - Pre => X in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - -- Ghost function that computes the value corresponding to an hexadecimal - -- digit. - - function Scan_Overflows_Ghost - (Digit : Uns; - Base : Uns; - Acc : Uns) return Boolean - is - (Digit >= Base - or else Acc > Uns'Last / Base - or else Uns'Last - Digit < Base * Acc) - with Ghost; - -- Ghost function which returns True if Digit + Base * Acc overflows or - -- Digit is greater than Base, as this is used by the algorithm for the - -- test of overflow. - - function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) return Uns_Option - with - Ghost, - Subprogram_Variant => (Increases => From), - Pre => Str'Last /= Positive'Last - and then - (From > To or else (From >= Str'First and then To <= Str'Last)) - and then Only_Hexa_Ghost (Str, From, To); - -- Ghost function that recursively computes the based number in Str, - -- assuming Acc has been scanned already and scanning continues at index - -- From. - - function Exponent_Unsigned_Ghost - (Value : Uns; - Exp : Natural; - Base : Uns := 10) return Uns_Option - with - Ghost, - Subprogram_Variant => (Decreases => Exp); - -- Ghost function that recursively computes Value * Base ** Exp - - function Is_Raw_Unsigned_Format_Ghost (Str : String) return Boolean is - (Is_Natural_Format_Ghost (Str) - and then - (declare - Last_Num_Init : constant Integer := Last_Number_Ghost (Str); - Starts_As_Based : constant Boolean := - Last_Num_Init < Str'Last - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Str (Last_Num_Init + 2) in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - Last_Num_Based : constant Integer := - (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Str'Last)) - else Last_Num_Init); - Is_Based : constant Boolean := - Starts_As_Based - and then Last_Num_Based < Str'Last - and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); - First_Exp : constant Integer := - (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); - begin - (if Starts_As_Based then - Is_Based_Format_Ghost (Str (Last_Num_Init + 2 .. Str'Last)) - and then Last_Num_Based < Str'Last) - and then Is_Opt_Exponent_Format_Ghost - (Str (First_Exp .. Str'Last)))) - with - Ghost, - Pre => Str'Last /= Positive'Last, - Post => True; - -- Ghost function that determines if Str has the correct format for an - -- unsigned number without a sign character. - -- It is a natural number in base 10, optionally followed by a based - -- number surrounded by delimiters # or :, optionally followed by an - -- exponent part. - - function Raw_Unsigned_Overflows_Ghost - (Str : String; - From, To : Integer) - return Boolean - is - (declare - Last_Num_Init : constant Integer := - Last_Number_Ghost (Str (From .. To)); - Init_Val : constant Uns_Option := - Scan_Based_Number_Ghost (Str, From, Last_Num_Init); - Starts_As_Based : constant Boolean := - Last_Num_Init < To - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Str (Last_Num_Init + 2) in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - Last_Num_Based : constant Integer := - (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) - else Last_Num_Init); - Is_Based : constant Boolean := - Starts_As_Based - and then Last_Num_Based < To - and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); - Based_Val : constant Uns_Option := - (if Starts_As_Based and then not Init_Val.Overflow - then Scan_Based_Number_Ghost - (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value) - else Init_Val); - First_Exp : constant Integer := - (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); - Expon : constant Natural := - (if Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) - then Scan_Exponent_Ghost (Str (First_Exp .. To)) - else 0); - begin - Init_Val.Overflow - or else - (Last_Num_Init < To - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Init_Val.Value not in 2 .. 16) - or else - (Starts_As_Based - and then Based_Val.Overflow) - or else - (Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) - and then - (declare - Base : constant Uns := - (if Is_Based then Init_Val.Value else 10); - Value : constant Uns := - (if Is_Based then Based_Val.Value else Init_Val.Value); - begin - Exponent_Unsigned_Ghost - (Value, Expon, Base).Overflow))) - with - Ghost, - Pre => Str'Last /= Positive'Last - and then From in Str'Range - and then To in From .. Str'Last - and then Str (From) in '0' .. '9', - Post => True; - -- Ghost function that determines if the computation of the unsigned number - -- represented by Str will overflow. The computation overflows if either: - -- * The computation of the decimal part overflows, - -- * The decimal part is followed by a valid delimiter for a based - -- part, and the number corresponding to the base is not a valid base, - -- * The computation of the based part overflows, or - -- * There is an exponent and the computation of the exponentiation - -- overflows. - - function Scan_Raw_Unsigned_Ghost - (Str : String; - From, To : Integer) - return Uns - is - (declare - Last_Num_Init : constant Integer := - Last_Number_Ghost (Str (From .. To)); - Init_Val : constant Uns_Option := - Scan_Based_Number_Ghost (Str, From, Last_Num_Init); - Starts_As_Based : constant Boolean := - Last_Num_Init < To - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Str (Last_Num_Init + 2) in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - Last_Num_Based : constant Integer := - (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) - else Last_Num_Init); - Is_Based : constant Boolean := - Starts_As_Based - and then Last_Num_Based < To - and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); - Based_Val : constant Uns_Option := - (if Starts_As_Based and then not Init_Val.Overflow - then Scan_Based_Number_Ghost - (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value) - else Init_Val); - First_Exp : constant Integer := - (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); - Expon : constant Natural := - (if Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) - then Scan_Exponent_Ghost (Str (First_Exp .. To)) - else 0); - Base : constant Uns := - (if Is_Based then Init_Val.Value else 10); - Value : constant Uns := - (if Is_Based then Based_Val.Value else Init_Val.Value); - begin - Exponent_Unsigned_Ghost (Value, Expon, Base).Value) - with - Ghost, - Pre => Str'Last /= Positive'Last - and then From in Str'Range - and then To in From .. Str'Last - and then Str (From) in '0' .. '9' - and then not Raw_Unsigned_Overflows_Ghost (Str, From, To), - Post => True; - -- Ghost function that scans an unsigned number without a sign character - - function Raw_Unsigned_Last_Ghost - (Str : String; - From, To : Integer) - return Positive - is - (declare - Last_Num_Init : constant Integer := - Last_Number_Ghost (Str (From .. To)); - Starts_As_Based : constant Boolean := - Last_Num_Init < To - 1 - and then Str (Last_Num_Init + 1) in '#' | ':' - and then Str (Last_Num_Init + 2) in - '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; - Last_Num_Based : constant Integer := - (if Starts_As_Based - then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) - else Last_Num_Init); - Is_Based : constant Boolean := - Starts_As_Based - and then Last_Num_Based < To - and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); - First_Exp : constant Integer := - (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); - begin - (if not Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) - then First_Exp - elsif Str (First_Exp + 1) in '-' | '+' then - Last_Number_Ghost (Str (First_Exp + 2 .. To)) + 1 - else Last_Number_Ghost (Str (First_Exp + 1 .. To)) + 1)) - with - Ghost, - Pre => Str'Last /= Positive'Last - and then From in Str'Range - and then To in From .. Str'Last - and then Str (From) in '0' .. '9', - Post => Raw_Unsigned_Last_Ghost'Result in From .. To + 1; - -- Ghost function that returns the position of the cursor once an unsigned - -- number has been seen. + package Spec is new System.Value_U_Spec (Uns); procedure Scan_Raw_Unsigned (Str : String; @@ -373,10 +64,10 @@ package System.Value_U is with Pre => Str'Last /= Positive'Last and then Ptr.all in Str'Range and then Max in Ptr.all .. Str'Last - and then Is_Raw_Unsigned_Format_Ghost (Str (Ptr.all .. Max)), - Post => not Raw_Unsigned_Overflows_Ghost (Str, Ptr.all'Old, Max) - and Res = Scan_Raw_Unsigned_Ghost (Str, Ptr.all'Old, Max) - and Ptr.all = Raw_Unsigned_Last_Ghost (Str, Ptr.all'Old, Max); + and then Spec.Is_Raw_Unsigned_Format_Ghost (Str (Ptr.all .. Max)), + Post => Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr.all'Old, Max) + and Res = Spec.Scan_Raw_Unsigned_Ghost (Str, Ptr.all'Old, Max) + and Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Ptr.all'Old, Max); -- This function scans the string starting at Str (Ptr.all) for a valid -- integer according to the syntax described in (RM 3.5(43)). The substring @@ -464,7 +155,7 @@ package System.Value_U is Fst_Num : constant Positive := (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); begin - Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Max))), + Spec.Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Max))), Post => (declare Non_Blank : constant Positive := @@ -472,9 +163,9 @@ package System.Value_U is Fst_Num : constant Positive := (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); begin - not Raw_Unsigned_Overflows_Ghost (Str, Fst_Num, Max) - and then Res = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max) - and then Ptr.all = Raw_Unsigned_Last_Ghost (Str, Fst_Num, Max)); + Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Max) + and then Res = Spec.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max) + and then Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Fst_Num, Max)); -- Same as Scan_Raw_Unsigned, except scans optional leading -- blanks, and an optional leading plus sign. @@ -482,157 +173,18 @@ package System.Value_U is -- Note: if a minus sign is present, Constraint_Error will be raised. -- Note: trailing blanks are not scanned. - function Slide_To_1 (Str : String) return String - with Ghost, - Post => - Only_Space_Ghost (Str, Str'First, Str'Last) = - (for all J in Str'First .. Str'Last => - Slide_To_1'Result (J - Str'First + 1) = ' '); - -- Slides Str so that it starts at 1 - - function Slide_If_Necessary (Str : String) return String is - (if Str'Last = Positive'Last then Slide_To_1 (Str) else Str) - with Ghost, - Post => - Only_Space_Ghost (Str, Str'First, Str'Last) = - Only_Space_Ghost (Slide_If_Necessary'Result, - Slide_If_Necessary'Result'First, - Slide_If_Necessary'Result'Last); - -- If Str'Last = Positive'Last then slides Str so that it starts at 1 - - function Is_Unsigned_Ghost (Str : String) return Boolean is - (declare - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - Fst_Num : constant Positive := - (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); - begin - Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last)) - and then not Raw_Unsigned_Overflows_Ghost (Str, Fst_Num, Str'Last) - and then Only_Space_Ghost - (Str, Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last), Str'Last)) - with Ghost, - Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) - and then Str'Last /= Positive'Last, - Post => True; - -- Ghost function that determines if Str has the correct format for an - -- unsigned number, consisting in some blank characters, an optional - -- + sign, a raw unsigned number which does not overflow and then some - -- more blank characters. - - function Is_Value_Unsigned_Ghost (Str : String; Val : Uns) return Boolean is - (declare - Non_Blank : constant Positive := First_Non_Space_Ghost - (Str, Str'First, Str'Last); - Fst_Num : constant Positive := - (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); - begin - Val = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last)) - with Ghost, - Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) - and then Str'Last /= Positive'Last - and then Is_Unsigned_Ghost (Str), - Post => True; - -- Ghost function that returns True if Val is the value corresponding to - -- the unsigned number represented by Str. - function Value_Unsigned (Str : String) return Uns - with Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) - and then Str'Length /= Positive'Last - and then Is_Unsigned_Ghost (Slide_If_Necessary (Str)), + with Pre => Str'Length /= Positive'Last + and then not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Spec.Is_Unsigned_Ghost (Spec.Slide_If_Necessary (Str)), Post => - Is_Value_Unsigned_Ghost - (Slide_If_Necessary (Str), Value_Unsigned'Result), + Spec.Is_Value_Unsigned_Ghost + (Spec.Slide_If_Necessary (Str), Value_Unsigned'Result), Subprogram_Variant => (Decreases => Str'First); -- Used in computing X'Value (Str) where X is a modular integer type whose -- modulus does not exceed the range of System.Unsigned_Types.Unsigned. Str -- is the string argument of the attribute. Constraint_Error is raised if -- the string is malformed, or if the value is out of range. - procedure Prove_Iter_Scan_Based_Number_Ghost - (Str1, Str2 : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) - with - Ghost, - Subprogram_Variant => (Increases => From), - Pre => Str1'Last /= Positive'Last - and then Str2'Last /= Positive'Last - and then - (From > To or else (From >= Str1'First and then To <= Str1'Last)) - and then - (From > To or else (From >= Str2'First and then To <= Str2'Last)) - and then Only_Hexa_Ghost (Str1, From, To) - and then (for all J in From .. To => Str1 (J) = Str2 (J)), - Post => - Scan_Based_Number_Ghost (Str1, From, To, Base, Acc) - = Scan_Based_Number_Ghost (Str2, From, To, Base, Acc); - -- Ghost lemma used in the proof of 'Image implementation, to prove the - -- preservation of Scan_Based_Number_Ghost across an update in the string - -- in lower indexes. - - procedure Prove_Scan_Only_Decimal_Ghost - (Str : String; - Val : Uns) - with - Ghost, - Pre => Str'Last /= Positive'Last - and then Str'Length >= 2 - and then Str (Str'First) = ' ' - and then Only_Decimal_Ghost (Str, Str'First + 1, Str'Last) - and then Scan_Based_Number_Ghost (Str, Str'First + 1, Str'Last) - = Wrap_Option (Val), - Post => Is_Unsigned_Ghost (Slide_If_Necessary (Str)) - and then Value_Unsigned (Str) = Val; - -- Ghost lemma used in the proof of 'Image implementation, to prove that - -- the result of Value_Unsigned on a decimal string is the same as the - -- result of Scan_Based_Number_Ghost. - -private - - ----------------------------- - -- Exponent_Unsigned_Ghost -- - ----------------------------- - - function Exponent_Unsigned_Ghost - (Value : Uns; - Exp : Natural; - Base : Uns := 10) return Uns_Option - is - (if Exp = 0 or Value = 0 then (Overflow => False, Value => Value) - elsif Scan_Overflows_Ghost (0, Base, Value) then (Overflow => True) - else Exponent_Unsigned_Ghost (Value * Base, Exp - 1, Base)); - - ----------------------------- - -- Scan_Based_Number_Ghost -- - ----------------------------- - - function Scan_Based_Number_Ghost - (Str : String; - From, To : Integer; - Base : Uns := 10; - Acc : Uns := 0) return Uns_Option - is - (if From > To then (Overflow => False, Value => Acc) - elsif Str (From) = '_' - then Scan_Based_Number_Ghost (Str, From + 1, To, Base, Acc) - elsif Scan_Overflows_Ghost - (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc) - then (Overflow => True) - else Scan_Based_Number_Ghost - (Str, From + 1, To, Base, - Base * Acc + Hexa_To_Unsigned_Ghost (Str (From)))); - - ---------------- - -- Slide_To_1 -- - ---------------- - - function Slide_To_1 (Str : String) return String is - (declare - Res : constant String (1 .. Str'Length) := Str; - begin - Res); - end System.Value_U; diff --git a/gcc/ada/libgnat/s-valuti.ads b/gcc/ada/libgnat/s-valuti.ads index 2b89b12..7c2da17 100644 --- a/gcc/ada/libgnat/s-valuti.ads +++ b/gcc/ada/libgnat/s-valuti.ads @@ -374,48 +374,274 @@ is -- no check for this case, the caller must ensure this condition is met. pragma Warnings (GNATprove, On, """Ptr"" is not modified"); - -- Bundle Int type with other types, constants and subprograms used in + -- Bundle Uns type with other types, constants and subprograms used in -- ghost code, so that this package can be instantiated once and used - -- multiple times as generic formal for a given Int type. + -- multiple times as generic formal for a given Uns type. generic - type Int is range <>; type Uns is mod <>; - type Uns_Option is private; + type P_Uns_Option is private with Ghost; + with function P_Wrap_Option (Value : Uns) return P_Uns_Option + with Ghost; + with function P_Hexa_To_Unsigned_Ghost (X : Character) return Uns + with Ghost; + with function P_Scan_Overflows_Ghost + (Digit : Uns; + Base : Uns; + Acc : Uns) return Boolean + with Ghost; + with function P_Is_Raw_Unsigned_Format_Ghost + (Str : String) return Boolean + with Ghost; + with function P_Scan_Split_No_Overflow_Ghost + (Str : String; + From, To : Integer) + return Boolean + with Ghost; + with function P_Raw_Unsigned_No_Overflow_Ghost + (Str : String; + From, To : Integer) + return Boolean + with Ghost; - Unsigned_Width_Ghost : Natural; + with function P_Exponent_Unsigned_Ghost + (Value : Uns; + Exp : Natural; + Base : Uns := 10) return P_Uns_Option + with Ghost; + with procedure P_Lemma_Exponent_Unsigned_Ghost_Base + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with Ghost; + with procedure P_Lemma_Exponent_Unsigned_Ghost_Overflow + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with Ghost; + with procedure P_Lemma_Exponent_Unsigned_Ghost_Step + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with Ghost; - with function Wrap_Option (Value : Uns) return Uns_Option - with Ghost; - with function Only_Decimal_Ghost + with function P_Scan_Raw_Unsigned_Ghost (Str : String; From, To : Integer) - return Boolean - with Ghost; - with function Hexa_To_Unsigned_Ghost (X : Character) return Uns - with Ghost; - with function Scan_Based_Number_Ghost + return Uns + with Ghost; + with procedure P_Lemma_Scan_Based_Number_Ghost_Base (Str : String; From, To : Integer; Base : Uns := 10; Acc : Uns := 0) - return Uns_Option - with Ghost; - with function Is_Integer_Ghost (Str : String) return Boolean - with Ghost; - with procedure Prove_Iter_Scan_Based_Number_Ghost + with Ghost; + with procedure P_Lemma_Scan_Based_Number_Ghost_Underscore + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with Ghost; + with procedure P_Lemma_Scan_Based_Number_Ghost_Overflow + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with Ghost; + with procedure P_Lemma_Scan_Based_Number_Ghost_Step + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with Ghost; + + with function P_Raw_Unsigned_Last_Ghost + (Str : String; + From, To : Integer) + return Positive + with Ghost; + with function P_Only_Decimal_Ghost + (Str : String; + From, To : Integer) + return Boolean + with Ghost; + with function P_Scan_Based_Number_Ghost + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + return P_Uns_Option + with Ghost; + with function P_Is_Unsigned_Ghost (Str : String) return Boolean + with Ghost; + with function P_Is_Value_Unsigned_Ghost + (Str : String; + Val : Uns) return Boolean + with Ghost; + + with procedure P_Prove_Scan_Only_Decimal_Ghost + (Str : String; + Val : Uns) + with Ghost; + with procedure P_Prove_Scan_Based_Number_Ghost_Eq (Str1, Str2 : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with Ghost; + + package Uns_Params is + subtype Uns_Option is P_Uns_Option with Ghost; + function Wrap_Option (Value : Uns) return Uns_Option renames + P_Wrap_Option; + function Hexa_To_Unsigned_Ghost + (X : Character) return Uns + renames P_Hexa_To_Unsigned_Ghost; + function Scan_Overflows_Ghost + (Digit : Uns; + Base : Uns; + Acc : Uns) return Boolean + renames P_Scan_Overflows_Ghost; + function Is_Raw_Unsigned_Format_Ghost + (Str : String) return Boolean + renames P_Is_Raw_Unsigned_Format_Ghost; + function Scan_Split_No_Overflow_Ghost + (Str : String; + From, To : Integer) return Boolean + renames P_Scan_Split_No_Overflow_Ghost; + function Raw_Unsigned_No_Overflow_Ghost + (Str : String; + From, To : Integer) return Boolean + renames P_Raw_Unsigned_No_Overflow_Ghost; + + function Exponent_Unsigned_Ghost + (Value : Uns; + Exp : Natural; + Base : Uns := 10) return Uns_Option + renames P_Exponent_Unsigned_Ghost; + procedure Lemma_Exponent_Unsigned_Ghost_Base + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + renames P_Lemma_Exponent_Unsigned_Ghost_Base; + procedure Lemma_Exponent_Unsigned_Ghost_Overflow + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + renames P_Lemma_Exponent_Unsigned_Ghost_Overflow; + procedure Lemma_Exponent_Unsigned_Ghost_Step + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + renames P_Lemma_Exponent_Unsigned_Ghost_Step; + + function Scan_Raw_Unsigned_Ghost + (Str : String; + From, To : Integer) return Uns + renames P_Scan_Raw_Unsigned_Ghost; + procedure Lemma_Scan_Based_Number_Ghost_Base + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + renames P_Lemma_Scan_Based_Number_Ghost_Base; + procedure Lemma_Scan_Based_Number_Ghost_Underscore + (Str : String; From, To : Integer; Base : Uns := 10; Acc : Uns := 0) + renames P_Lemma_Scan_Based_Number_Ghost_Underscore; + procedure Lemma_Scan_Based_Number_Ghost_Overflow + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + renames P_Lemma_Scan_Based_Number_Ghost_Overflow; + procedure Lemma_Scan_Based_Number_Ghost_Step + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + renames P_Lemma_Scan_Based_Number_Ghost_Step; + + function Raw_Unsigned_Last_Ghost + (Str : String; + From, To : Integer) return Positive + renames P_Raw_Unsigned_Last_Ghost; + function Only_Decimal_Ghost + (Str : String; + From, To : Integer) return Boolean + renames P_Only_Decimal_Ghost; + function Scan_Based_Number_Ghost + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) return Uns_Option + renames P_Scan_Based_Number_Ghost; + function Is_Unsigned_Ghost (Str : String) return Boolean + renames P_Is_Unsigned_Ghost; + function Is_Value_Unsigned_Ghost + (Str : String; + Val : Uns) return Boolean + renames P_Is_Value_Unsigned_Ghost; + + procedure Prove_Scan_Only_Decimal_Ghost + (Str : String; + Val : Uns) + renames P_Prove_Scan_Only_Decimal_Ghost; + procedure Prove_Scan_Based_Number_Ghost_Eq + (Str1, Str2 : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + renames P_Prove_Scan_Based_Number_Ghost_Eq; + end Uns_Params; + + -- Bundle Int type with other types, constants and subprograms used in + -- ghost code, so that this package can be instantiated once and used + -- multiple times as generic formal for a given Int type. + generic + type Int is range <>; + type Uns is mod <>; + + with package P_Uns_Params is new System.Val_Util.Uns_Params + (Uns => Uns, others => <>) + with Ghost; + + with function P_Abs_Uns_Of_Int (Val : Int) return Uns + with Ghost; + with function P_Is_Int_Of_Uns + (Minus : Boolean; + Uval : Uns; + Val : Int) + return Boolean with Ghost; - with procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) + with function P_Is_Integer_Ghost (Str : String) return Boolean with Ghost; - with function Abs_Uns_Of_Int (Val : Int) return Uns + with function P_Is_Value_Integer_Ghost + (Str : String; + Val : Int) return Boolean with Ghost; - with function Value_Integer (Str : String) return Int + with procedure P_Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) with Ghost; package Int_Params is + package Uns_Params renames P_Uns_Params; + function Abs_Uns_Of_Int (Val : Int) return Uns renames + P_Abs_Uns_Of_Int; + function Is_Int_Of_Uns + (Minus : Boolean; + Uval : Uns; + Val : Int) + return Boolean + renames P_Is_Int_Of_Uns; + function Is_Integer_Ghost (Str : String) return Boolean renames + P_Is_Integer_Ghost; + function Is_Value_Integer_Ghost + (Str : String; + Val : Int) return Boolean + renames P_Is_Value_Integer_Ghost; + procedure Prove_Scan_Only_Decimal_Ghost (Str : String; Val : Int) renames + P_Prove_Scan_Only_Decimal_Ghost; end Int_Params; private diff --git a/gcc/ada/libgnat/s-vauspe.adb b/gcc/ada/libgnat/s-vauspe.adb new file mode 100644 index 0000000..1a870b9 --- /dev/null +++ b/gcc/ada/libgnat/s-vauspe.adb @@ -0,0 +1,198 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . V A L U E _ U _ S P E C -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2022-2022, Free Software Foundation, Inc. -- +-- -- +-- GNAT 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/>. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +pragma Assertion_Policy (Pre => Ignore, + Post => Ignore, + Contract_Cases => Ignore, + Ghost => Ignore, + Subprogram_Variant => Ignore); + +package body System.Value_U_Spec with SPARK_Mode is + + ----------------------------- + -- Exponent_Unsigned_Ghost -- + ----------------------------- + + function Exponent_Unsigned_Ghost + (Value : Uns; + Exp : Natural; + Base : Uns := 10) return Uns_Option + is + (if Exp = 0 or Value = 0 then (Overflow => False, Value => Value) + elsif Scan_Overflows_Ghost (0, Base, Value) then (Overflow => True) + else Exponent_Unsigned_Ghost (Value * Base, Exp - 1, Base)); + + --------------------- + -- Last_Hexa_Ghost -- + --------------------- + + function Last_Hexa_Ghost (Str : String) return Positive is + begin + for J in Str'Range loop + if Str (J) not in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_' then + return J - 1; + end if; + + pragma Loop_Invariant + (for all K in Str'First .. J => + Str (K) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'); + end loop; + + return Str'Last; + end Last_Hexa_Ghost; + + ----------------------------- + -- Lemmas with null bodies -- + ----------------------------- + + procedure Lemma_Scan_Based_Number_Ghost_Base + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + is null; + + procedure Lemma_Scan_Based_Number_Ghost_Underscore + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + is null; + + procedure Lemma_Scan_Based_Number_Ghost_Overflow + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + is null; + + procedure Lemma_Scan_Based_Number_Ghost_Step + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + is null; + + procedure Lemma_Exponent_Unsigned_Ghost_Base + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + is null; + + procedure Lemma_Exponent_Unsigned_Ghost_Overflow + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + is null; + + procedure Lemma_Exponent_Unsigned_Ghost_Step + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + is null; + + -------------------------------------- + -- Prove_Scan_Based_Number_Ghost_Eq -- + -------------------------------------- + + procedure Prove_Scan_Based_Number_Ghost_Eq + (Str1, Str2 : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + is + begin + if From > To then + null; + elsif Str1 (From) = '_' then + Prove_Scan_Based_Number_Ghost_Eq + (Str1, Str2, From + 1, To, Base, Acc); + elsif Scan_Overflows_Ghost + (Hexa_To_Unsigned_Ghost (Str1 (From)), Base, Acc) + then + null; + else + Prove_Scan_Based_Number_Ghost_Eq + (Str1, Str2, From + 1, To, Base, + Base * Acc + Hexa_To_Unsigned_Ghost (Str1 (From))); + end if; + end Prove_Scan_Based_Number_Ghost_Eq; + + ----------------------------------- + -- Prove_Scan_Only_Decimal_Ghost -- + ----------------------------------- + + procedure Prove_Scan_Only_Decimal_Ghost + (Str : String; + Val : Uns) + is + pragma Assert (Str (Str'First + 1) /= ' '); + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + pragma Assert (Non_Blank = Str'First + 1); + Fst_Num : constant Positive := + (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); + pragma Assert (Fst_Num = Str'First + 1); + begin + pragma Assert + (Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last))); + pragma Assert + (Scan_Split_No_Overflow_Ghost (Str, Str'First + 1, Str'Last)); + pragma Assert + ((Val, 10, 0) = Scan_Split_Value_Ghost (Str, Str'First + 1, Str'Last)); + pragma Assert + (Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Str'Last)); + pragma Assert (Val = Exponent_Unsigned_Ghost (Val, 0, 10).Value); + pragma Assert (Is_Unsigned_Ghost (Str)); + pragma Assert (Is_Value_Unsigned_Ghost (Str, Val)); + end Prove_Scan_Only_Decimal_Ghost; + + ----------------------------- + -- Scan_Based_Number_Ghost -- + ----------------------------- + + function Scan_Based_Number_Ghost + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) return Uns_Option + is + (if From > To then (Overflow => False, Value => Acc) + elsif Str (From) = '_' + then Scan_Based_Number_Ghost (Str, From + 1, To, Base, Acc) + elsif Scan_Overflows_Ghost + (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc) + then (Overflow => True) + else Scan_Based_Number_Ghost + (Str, From + 1, To, Base, + Base * Acc + Hexa_To_Unsigned_Ghost (Str (From)))); + +end System.Value_U_Spec; diff --git a/gcc/ada/libgnat/s-vauspe.ads b/gcc/ada/libgnat/s-vauspe.ads new file mode 100644 index 0000000..0d5c19e --- /dev/null +++ b/gcc/ada/libgnat/s-vauspe.ads @@ -0,0 +1,639 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT COMPILER COMPONENTS -- +-- -- +-- S Y S T E M . V A L U E _ U _ S P E C -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2022-2022, Free Software Foundation, Inc. -- +-- -- +-- GNAT 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/>. -- +-- -- +-- GNAT was originally developed by the GNAT team at New York University. -- +-- Extensive contributions were provided by Ada Core Technologies Inc. -- +-- -- +------------------------------------------------------------------------------ + +-- This package contains the specification entities using for the formal +-- verification of the routines for scanning modular Unsigned values. + +-- Preconditions in this unit are meant for analysis only, not for run-time +-- checking, so that the expected exceptions are raised. This is enforced by +-- setting the corresponding assertion policy to Ignore. Postconditions and +-- contract cases should not be executed at runtime as well, in order not to +-- slow down the execution of these functions. + +pragma Assertion_Policy (Pre => Ignore, + Post => Ignore, + Contract_Cases => Ignore, + Ghost => Ignore, + Subprogram_Variant => Ignore); + +with System.Val_Util; use System.Val_Util; + +generic + + type Uns is mod <>; + +package System.Value_U_Spec with + Ghost, + SPARK_Mode, + Annotate => (GNATprove, Always_Return) +is + pragma Preelaborate; + + type Uns_Option (Overflow : Boolean := False) is record + case Overflow is + when True => + null; + when False => + Value : Uns := 0; + end case; + end record; + + function Wrap_Option (Value : Uns) return Uns_Option is + (Overflow => False, Value => Value); + + function Only_Decimal_Ghost + (Str : String; + From, To : Integer) + return Boolean + is + (for all J in From .. To => Str (J) in '0' .. '9') + with + Pre => From > To or else (From >= Str'First and then To <= Str'Last); + -- Ghost function that returns True if S has only decimal characters + -- from index From to index To. + + function Only_Hexa_Ghost (Str : String; From, To : Integer) return Boolean + is + (for all J in From .. To => + Str (J) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_') + with + Pre => From > To or else (From >= Str'First and then To <= Str'Last); + -- Ghost function that returns True if S has only hexadecimal characters + -- from index From to index To. + + function Last_Hexa_Ghost (Str : String) return Positive + with + Pre => Str /= "" + and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F', + Post => Last_Hexa_Ghost'Result in Str'Range + and then (if Last_Hexa_Ghost'Result < Str'Last then + Str (Last_Hexa_Ghost'Result + 1) not in + '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_') + and then Only_Hexa_Ghost (Str, Str'First, Last_Hexa_Ghost'Result); + -- Ghost function that returns the index of the last character in S that + -- is either an hexadecimal digit or an underscore, which necessarily + -- exists given the precondition on Str. + + function Is_Based_Format_Ghost (Str : String) return Boolean + is + (Str /= "" + and then Str (Str'First) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' + and then + (declare + L : constant Positive := Last_Hexa_Ghost (Str); + begin + Str (L) /= '_' + and then (for all J in Str'First .. L => + (if Str (J) = '_' then Str (J + 1) /= '_')))); + -- Ghost function that determines if Str has the correct format for a + -- based number, consisting in a sequence of hexadecimal digits possibly + -- separated by single underscores. It may be followed by other characters. + + function Hexa_To_Unsigned_Ghost (X : Character) return Uns is + (case X is + when '0' .. '9' => Character'Pos (X) - Character'Pos ('0'), + when 'a' .. 'f' => Character'Pos (X) - Character'Pos ('a') + 10, + when 'A' .. 'F' => Character'Pos (X) - Character'Pos ('A') + 10, + when others => raise Program_Error) + with + Pre => X in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; + -- Ghost function that computes the value corresponding to an hexadecimal + -- digit. + + function Scan_Overflows_Ghost + (Digit : Uns; + Base : Uns; + Acc : Uns) return Boolean + is + (Digit >= Base + or else Acc > Uns'Last / Base + or else Uns'Last - Digit < Base * Acc); + -- Ghost function which returns True if Digit + Base * Acc overflows or + -- Digit is greater than Base, as this is used by the algorithm for the + -- test of overflow. + + function Scan_Based_Number_Ghost + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) return Uns_Option + with + Subprogram_Variant => (Increases => From), + Pre => Str'Last /= Positive'Last + and then + (From > To or else (From >= Str'First and then To <= Str'Last)) + and then Only_Hexa_Ghost (Str, From, To); + -- Ghost function that recursively computes the based number in Str, + -- assuming Acc has been scanned already and scanning continues at index + -- From. + + -- Lemmas unfolding the recursive definition of Scan_Based_Number_Ghost + + procedure Lemma_Scan_Based_Number_Ghost_Base + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with + Global => null, + Pre => Str'Last /= Positive'Last + and then + (From > To or else (From >= Str'First and then To <= Str'Last)) + and then Only_Hexa_Ghost (Str, From, To), + Post => + (if From > To + then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) = + (Overflow => False, Value => Acc)); + -- Base case: Scan_Based_Number_Ghost returns Acc if From is bigger than To + + procedure Lemma_Scan_Based_Number_Ghost_Underscore + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with + Global => null, + Pre => Str'Last /= Positive'Last + and then + (From > To or else (From >= Str'First and then To <= Str'Last)) + and then Only_Hexa_Ghost (Str, From, To), + Post => + (if From <= To and then Str (From) = '_' + then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) = + Scan_Based_Number_Ghost (Str, From + 1, To, Base, Acc)); + -- Underscore case: underscores are ignored while scanning + + procedure Lemma_Scan_Based_Number_Ghost_Overflow + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with + Global => null, + Pre => Str'Last /= Positive'Last + and then + (From > To or else (From >= Str'First and then To <= Str'Last)) + and then Only_Hexa_Ghost (Str, From, To), + Post => + (if From <= To + and then Str (From) /= '_' + and then Scan_Overflows_Ghost + (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc) + then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) = + (Overflow => True)); + -- Overflow case: scanning a digit which causes an overflow + + procedure Lemma_Scan_Based_Number_Ghost_Step + (Str : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with + Global => null, + Pre => Str'Last /= Positive'Last + and then + (From > To or else (From >= Str'First and then To <= Str'Last)) + and then Only_Hexa_Ghost (Str, From, To), + Post => + (if From <= To + and then Str (From) /= '_' + and then not Scan_Overflows_Ghost + (Hexa_To_Unsigned_Ghost (Str (From)), Base, Acc) + then Scan_Based_Number_Ghost (Str, From, To, Base, Acc) = + Scan_Based_Number_Ghost + (Str, From + 1, To, Base, + Base * Acc + Hexa_To_Unsigned_Ghost (Str (From)))); + -- Normal case: scanning a digit without overflows + + function Exponent_Unsigned_Ghost + (Value : Uns; + Exp : Natural; + Base : Uns := 10) return Uns_Option + with + Subprogram_Variant => (Decreases => Exp); + -- Ghost function that recursively computes Value * Base ** Exp + + -- Lemmas unfolding the recursive definition of Exponent_Unsigned_Ghost + + procedure Lemma_Exponent_Unsigned_Ghost_Base + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with + Post => + (if Exp = 0 or Value = 0 + then Exponent_Unsigned_Ghost (Value, Exp, Base) = + (Overflow => False, Value => Value)); + -- Base case: Exponent_Unsigned_Ghost returns 0 if Value or Exp is 0 + + procedure Lemma_Exponent_Unsigned_Ghost_Overflow + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with + Post => + (if Exp /= 0 + and then Value /= 0 + and then Scan_Overflows_Ghost (0, Base, Value) + then Exponent_Unsigned_Ghost (Value, Exp, Base) = (Overflow => True)); + -- Overflow case: the next multiplication overflows + + procedure Lemma_Exponent_Unsigned_Ghost_Step + (Value : Uns; + Exp : Natural; + Base : Uns := 10) + with + Post => + (if Exp /= 0 + and then Value /= 0 + and then not Scan_Overflows_Ghost (0, Base, Value) + then Exponent_Unsigned_Ghost (Value, Exp, Base) = + Exponent_Unsigned_Ghost (Value * Base, Exp - 1, Base)); + -- Normal case: exponentiation without overflows + + function Is_Raw_Unsigned_Format_Ghost (Str : String) return Boolean is + (Is_Natural_Format_Ghost (Str) + and then + (declare + Last_Num_Init : constant Integer := Last_Number_Ghost (Str); + Starts_As_Based : constant Boolean := + Last_Num_Init < Str'Last - 1 + and then Str (Last_Num_Init + 1) in '#' | ':' + and then Str (Last_Num_Init + 2) in + '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; + Last_Num_Based : constant Integer := + (if Starts_As_Based + then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Str'Last)) + else Last_Num_Init); + Is_Based : constant Boolean := + Starts_As_Based + and then Last_Num_Based < Str'Last + and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); + First_Exp : constant Integer := + (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); + begin + (if Starts_As_Based then + Is_Based_Format_Ghost (Str (Last_Num_Init + 2 .. Str'Last)) + and then Last_Num_Based < Str'Last) + and then Is_Opt_Exponent_Format_Ghost + (Str (First_Exp .. Str'Last)))) + with + Pre => Str'Last /= Positive'Last; + -- Ghost function that determines if Str has the correct format for an + -- unsigned number without a sign character. + -- It is a natural number in base 10, optionally followed by a based + -- number surrounded by delimiters # or :, optionally followed by an + -- exponent part. + + type Split_Value_Ghost is record + Value : Uns; + Base : Uns; + Expon : Natural; + end record; + + function Scan_Split_No_Overflow_Ghost + (Str : String; + From, To : Integer) + return Boolean + is + (declare + Last_Num_Init : constant Integer := + Last_Number_Ghost (Str (From .. To)); + Init_Val : constant Uns_Option := + Scan_Based_Number_Ghost (Str, From, Last_Num_Init); + Starts_As_Based : constant Boolean := + Last_Num_Init < To - 1 + and then Str (Last_Num_Init + 1) in '#' | ':' + and then Str (Last_Num_Init + 2) in + '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; + Last_Num_Based : constant Integer := + (if Starts_As_Based + then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) + else Last_Num_Init); + Based_Val : constant Uns_Option := + (if Starts_As_Based and then not Init_Val.Overflow + then Scan_Based_Number_Ghost + (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value) + else Init_Val); + begin + not Init_Val.Overflow + and then + (Last_Num_Init >= To - 1 + or else Str (Last_Num_Init + 1) not in '#' | ':' + or else Init_Val.Value in 2 .. 16) + and then + (not Starts_As_Based + or else not Based_Val.Overflow)) + with + Pre => Str'Last /= Positive'Last + and then From in Str'Range + and then To in From .. Str'Last + and then Str (From) in '0' .. '9'; + -- Ghost function that determines if an overflow might occur while scanning + -- the representation of an unsigned number. The computation overflows if + -- either: + -- * The computation of the decimal part overflows, + -- * The decimal part is followed by a valid delimiter for a based + -- part, and the number corresponding to the base is not a valid base, + -- or + -- * The computation of the based part overflows. + + pragma Warnings (Off, "constant * is not referenced"); + function Scan_Split_Value_Ghost + (Str : String; + From, To : Integer) + return Split_Value_Ghost + is + (declare + Last_Num_Init : constant Integer := + Last_Number_Ghost (Str (From .. To)); + Init_Val : constant Uns_Option := + Scan_Based_Number_Ghost (Str, From, Last_Num_Init); + Starts_As_Based : constant Boolean := + Last_Num_Init < To - 1 + and then Str (Last_Num_Init + 1) in '#' | ':' + and then Str (Last_Num_Init + 2) in + '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; + Last_Num_Based : constant Integer := + (if Starts_As_Based + then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) + else Last_Num_Init); + Is_Based : constant Boolean := + Starts_As_Based + and then Last_Num_Based < To + and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); + Based_Val : constant Uns_Option := + (if Starts_As_Based and then not Init_Val.Overflow + then Scan_Based_Number_Ghost + (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value) + else Init_Val); + First_Exp : constant Integer := + (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); + Expon : constant Natural := + (if Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) + then Scan_Exponent_Ghost (Str (First_Exp .. To)) + else 0); + Base : constant Uns := + (if Is_Based then Init_Val.Value else 10); + Value : constant Uns := + (if Is_Based then Based_Val.Value else Init_Val.Value); + begin + (Value => Value, Base => Base, Expon => Expon)) + with + Pre => Str'Last /= Positive'Last + and then From in Str'Range + and then To in From .. Str'Last + and then Str (From) in '0' .. '9' + and then Scan_Split_No_Overflow_Ghost (Str, From, To); + -- Ghost function that scans an unsigned number without a sign character + -- and return a record containing the values scanned for its value, its + -- base, and its exponent. + pragma Warnings (On, "constant * is not referenced"); + + function Raw_Unsigned_No_Overflow_Ghost + (Str : String; + From, To : Integer) + return Boolean + is + (Scan_Split_No_Overflow_Ghost (Str, From, To) + and then + (declare + Val : constant Split_Value_Ghost := Scan_Split_Value_Ghost + (Str, From, To); + begin + not Exponent_Unsigned_Ghost + (Val.Value, Val.Expon, Val.Base).Overflow)) + with + Pre => Str'Last /= Positive'Last + and then From in Str'Range + and then To in From .. Str'Last + and then Str (From) in '0' .. '9'; + -- Ghost function that determines if the computation of the unsigned number + -- represented by Str will overflow. The computation overflows if either: + -- * The scan of the string overflows, or + -- * The computation of the exponentiation overflows. + + function Scan_Raw_Unsigned_Ghost + (Str : String; + From, To : Integer) + return Uns + is + (declare + Val : constant Split_Value_Ghost := Scan_Split_Value_Ghost + (Str, From, To); + begin + Exponent_Unsigned_Ghost (Val.Value, Val.Expon, Val.Base).Value) + with + Pre => Str'Last /= Positive'Last + and then From in Str'Range + and then To in From .. Str'Last + and then Str (From) in '0' .. '9' + and then Raw_Unsigned_No_Overflow_Ghost (Str, From, To); + -- Ghost function that scans an unsigned number without a sign character + + function Raw_Unsigned_Last_Ghost + (Str : String; + From, To : Integer) + return Positive + is + (declare + Last_Num_Init : constant Integer := + Last_Number_Ghost (Str (From .. To)); + Starts_As_Based : constant Boolean := + Last_Num_Init < To - 1 + and then Str (Last_Num_Init + 1) in '#' | ':' + and then Str (Last_Num_Init + 2) in + '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'; + Last_Num_Based : constant Integer := + (if Starts_As_Based + then Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. To)) + else Last_Num_Init); + Is_Based : constant Boolean := + Starts_As_Based + and then Last_Num_Based < To + and then Str (Last_Num_Based + 1) = Str (Last_Num_Init + 1); + First_Exp : constant Integer := + (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1); + begin + (if not Starts_As_Exponent_Format_Ghost (Str (First_Exp .. To)) + then First_Exp + elsif Str (First_Exp + 1) in '-' | '+' then + Last_Number_Ghost (Str (First_Exp + 2 .. To)) + 1 + else Last_Number_Ghost (Str (First_Exp + 1 .. To)) + 1)) + with + Pre => Str'Last /= Positive'Last + and then From in Str'Range + and then To in From .. Str'Last + and then Str (From) in '0' .. '9'; + -- Ghost function that returns the position of the cursor once an unsigned + -- number has been seen. + + function Slide_To_1 (Str : String) return String + with + Post => + Only_Space_Ghost (Str, Str'First, Str'Last) = + (for all J in Str'First .. Str'Last => + Slide_To_1'Result (J - Str'First + 1) = ' '); + -- Slides Str so that it starts at 1 + + function Slide_If_Necessary (Str : String) return String is + (if Str'Last = Positive'Last then Slide_To_1 (Str) else Str); + -- If Str'Last = Positive'Last then slides Str so that it starts at 1 + + function Is_Unsigned_Ghost (Str : String) return Boolean is + (declare + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + Fst_Num : constant Positive := + (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); + begin + Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Str'Last)) + and then Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Str'Last) + and then Only_Space_Ghost + (Str, Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last), Str'Last)) + with + Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Str'Last /= Positive'Last; + -- Ghost function that determines if Str has the correct format for an + -- unsigned number, consisting in some blank characters, an optional + -- + sign, a raw unsigned number which does not overflow and then some + -- more blank characters. + + function Is_Value_Unsigned_Ghost (Str : String; Val : Uns) return Boolean is + (declare + Non_Blank : constant Positive := First_Non_Space_Ghost + (Str, Str'First, Str'Last); + Fst_Num : constant Positive := + (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank); + begin + Val = Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last)) + with + Pre => not Only_Space_Ghost (Str, Str'First, Str'Last) + and then Str'Last /= Positive'Last + and then Is_Unsigned_Ghost (Str); + -- Ghost function that returns True if Val is the value corresponding to + -- the unsigned number represented by Str. + + procedure Prove_Scan_Based_Number_Ghost_Eq + (Str1, Str2 : String; + From, To : Integer; + Base : Uns := 10; + Acc : Uns := 0) + with + Subprogram_Variant => (Increases => From), + Pre => Str1'Last /= Positive'Last + and then Str2'Last /= Positive'Last + and then + (From > To or else (From >= Str1'First and then To <= Str1'Last)) + and then + (From > To or else (From >= Str2'First and then To <= Str2'Last)) + and then Only_Hexa_Ghost (Str1, From, To) + and then (for all J in From .. To => Str1 (J) = Str2 (J)), + Post => + Scan_Based_Number_Ghost (Str1, From, To, Base, Acc) + = Scan_Based_Number_Ghost (Str2, From, To, Base, Acc); + -- Scan_Based_Number_Ghost returns the same value on two slices which are + -- equal. + + procedure Prove_Scan_Only_Decimal_Ghost + (Str : String; + Val : Uns) + with + Pre => Str'Last /= Positive'Last + and then Str'Length >= 2 + and then Str (Str'First) = ' ' + and then Only_Decimal_Ghost (Str, Str'First + 1, Str'Last) + and then Scan_Based_Number_Ghost (Str, Str'First + 1, Str'Last) + = Wrap_Option (Val), + Post => Is_Unsigned_Ghost (Slide_If_Necessary (Str)) + and then + Is_Value_Unsigned_Ghost (Slide_If_Necessary (Str), Val); + -- Ghost lemma used in the proof of 'Image implementation, to prove that + -- the result of Value_Unsigned on a decimal string is the same as the + -- result of Scan_Based_Number_Ghost. + + -- Bundle Uns type with other types, constants and subprograms used in + -- ghost code, so that this package can be instantiated once and used + -- multiple times as generic formal for a given Int type. + + package Uns_Params is new System.Val_Util.Uns_Params + (Uns => Uns, + P_Uns_Option => Uns_Option, + P_Wrap_Option => Wrap_Option, + P_Hexa_To_Unsigned_Ghost => Hexa_To_Unsigned_Ghost, + P_Scan_Overflows_Ghost => Scan_Overflows_Ghost, + P_Is_Raw_Unsigned_Format_Ghost => + Is_Raw_Unsigned_Format_Ghost, + P_Scan_Split_No_Overflow_Ghost => + Scan_Split_No_Overflow_Ghost, + P_Raw_Unsigned_No_Overflow_Ghost => + Raw_Unsigned_No_Overflow_Ghost, + P_Exponent_Unsigned_Ghost => Exponent_Unsigned_Ghost, + P_Lemma_Exponent_Unsigned_Ghost_Base => + Lemma_Exponent_Unsigned_Ghost_Base, + P_Lemma_Exponent_Unsigned_Ghost_Overflow => + Lemma_Exponent_Unsigned_Ghost_Overflow, + P_Lemma_Exponent_Unsigned_Ghost_Step => + Lemma_Exponent_Unsigned_Ghost_Step, + P_Scan_Raw_Unsigned_Ghost => Scan_Raw_Unsigned_Ghost, + P_Lemma_Scan_Based_Number_Ghost_Base => + Lemma_Scan_Based_Number_Ghost_Base, + P_Lemma_Scan_Based_Number_Ghost_Underscore => + Lemma_Scan_Based_Number_Ghost_Underscore, + P_Lemma_Scan_Based_Number_Ghost_Overflow => + Lemma_Scan_Based_Number_Ghost_Overflow, + P_Lemma_Scan_Based_Number_Ghost_Step => + Lemma_Scan_Based_Number_Ghost_Step, + P_Raw_Unsigned_Last_Ghost => Raw_Unsigned_Last_Ghost, + P_Only_Decimal_Ghost => Only_Decimal_Ghost, + P_Scan_Based_Number_Ghost => Scan_Based_Number_Ghost, + P_Is_Unsigned_Ghost => + Is_Unsigned_Ghost, + P_Is_Value_Unsigned_Ghost => + Is_Value_Unsigned_Ghost, + P_Prove_Scan_Only_Decimal_Ghost => + Prove_Scan_Only_Decimal_Ghost, + P_Prove_Scan_Based_Number_Ghost_Eq => + Prove_Scan_Based_Number_Ghost_Eq); + +private + + ---------------- + -- Slide_To_1 -- + ---------------- + + function Slide_To_1 (Str : String) return String is + (declare + Res : constant String (1 .. Str'Length) := Str; + begin + Res); + +end System.Value_U_Spec; diff --git a/gcc/ada/libgnat/s-widthu.adb b/gcc/ada/libgnat/s-widthu.adb index 390942c..df5f224 100644 --- a/gcc/ada/libgnat/s-widthu.adb +++ b/gcc/ada/libgnat/s-widthu.adb @@ -73,6 +73,14 @@ package body System.Width_U is Ghost, Post => X / Y / Z = X / (Y * Z); + procedure Lemma_Euclidian (V, Q, F, R : Big_Integer) + with + Ghost, + Pre => F > 0 and then Q = V / F and then R = V rem F, + Post => V = Q * F + R; + -- Ghost lemma to prove the relation between the quotient/remainder of + -- division by F and the value V. + ---------------------- -- Lemma_Lower_Mult -- ---------------------- @@ -104,6 +112,12 @@ package body System.Width_U is pragma Assert (X / YZ = XYZ + R / YZ); end Lemma_Div_Twice; + --------------------- + -- Lemma_Euclidian -- + --------------------- + + procedure Lemma_Euclidian (V, Q, F, R : Big_Integer) is null; + -- Local variables W : Natural; @@ -152,7 +166,7 @@ package body System.Width_U is R : constant Big_Integer := Big (T_Init) rem F with Ghost; begin pragma Assert (Q < Big_10); - pragma Assert (Big (T_Init) = Q * F + R); + Lemma_Euclidian (Big (T_Init), Q, F, R); Lemma_Lower_Mult (Q, Big (9), F); pragma Assert (Big (T_Init) <= Big (9) * F + F - 1); pragma Assert (Big (T_Init) < Big_10 * F); diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads index 0490895..19a8b41 100644 --- a/gcc/ada/opt.ads +++ b/gcc/ada/opt.ads @@ -267,6 +267,10 @@ package Opt is -- Set to True to detect whether subprogram parameters and function results -- alias the same object(s). + Check_Elaboration_Flags : Boolean := True; + -- GNATBIND + -- Set to False if switch -k is set. + Check_Float_Overflow : Boolean := False; -- GNAT -- Set to True to check that operations on predefined unconstrained float diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb index 4ab4dcb..9a00d7b 100644 --- a/gcc/ada/par-ch4.adb +++ b/gcc/ada/par-ch4.adb @@ -3554,7 +3554,6 @@ package body Ch4 is when Tok_Of => Restore_Scan_State (State); Scan; -- past OF - Set_Defining_Identifier (Assoc_Node, Id); Iter_Spec := P_Iterator_Specification (Id); Set_Iterator_Specification (Assoc_Node, Iter_Spec); diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb index 3835588..1be3ef8 100644 --- a/gcc/ada/par-ch5.adb +++ b/gcc/ada/par-ch5.adb @@ -242,8 +242,8 @@ package body Ch5 is -- In Ada 2022, we allow declarative items to be mixed with -- statements. The loop below alternates between calling - -- P_Declarative_Items to parse zero or more declarative items, and - -- parsing a statement. + -- P_Declarative_Items to parse zero or more declarative items, + -- and parsing a statement. loop Ignore (Tok_Semicolon); @@ -255,26 +255,17 @@ package body Ch5 is (Statement_List, Declare_Expression => False, In_Spec => False, In_Statements => True); - -- Use the length of the list to determine whether we parsed any - -- declarative items. If so, it's an error pre-2022. ???We should - -- be calling Error_Msg_Ada_2022_Feature below, to advertise the - -- new feature, but that causes a lot of test diffs, so for now, - -- we mimic the old "...before begin" message. + -- Use the length of the list to determine whether we parsed + -- any declarative items. If so, it's an error unless language + -- extensions are enabled. if List_Length (Statement_List) > Num_Statements then if All_Errors_Mode or else No (Decl_Loc) then Decl_Loc := Sloc (Pick (Statement_List, Num_Statements + 1)); - if False then - Error_Msg_Ada_2022_Feature - ("declarations mixed with statements", - Sloc (Pick (Statement_List, Num_Statements + 1))); - else - if Ada_Version < Ada_2022 then - Error_Msg - ("declarations must come before BEGIN", Decl_Loc); - end if; - end if; + Error_Msg_GNAT_Extension + ("declarations mixed with statements", + Sloc (Pick (Statement_List, Num_Statements + 1))); end if; end if; end; diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 2cd8807..258e4ad 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -404,10 +404,6 @@ package body Sem_Aggr is -- The bounds of the aggregate itype are cooked up to look reasonable -- (in this particular case the bounds will be 1 .. 2). - function Is_Null_Aggregate (N : Node_Id) return Boolean; - -- Returns True for a "[]" aggregate (an Ada 2022 feature), even after - -- it has been transformed by expansion. Returns False otherwise. - procedure Make_String_Into_Aggregate (N : Node_Id); -- A string literal can appear in a context in which a one dimensional -- array of characters is expected. This procedure simply rewrites the @@ -419,9 +415,6 @@ package body Sem_Aggr is -- is constrained). If the subtype is unconstrained, then the bounds -- are determined in much the same way as the bounds for a null string -- literal with no applicable index constraint. - -- Emit a check that the bounds for each dimension define a null - -- range; no check is emitted if it is statically known that the - -- check would succeed. --------------------------------- -- Delta aggregate processing -- @@ -567,7 +560,29 @@ package body Sem_Aggr is end if; Set_Parent (Index_Constraints, N); - Collect_Aggr_Bounds (N, 1); + + -- When resolving a null aggregate we created a list of aggregate bounds + -- for the consecutive dimensions. The bounds for the first dimension + -- are attached as the Aggregate_Bounds of the aggregate node. + + if Is_Null_Aggregate (N) then + declare + This_Range : Node_Id := Aggregate_Bounds (N); + begin + for J in 1 .. Aggr_Dimension loop + Aggr_Range (J) := This_Range; + Next_Index (This_Range); + + -- Remove bounds from the list, so they can be reattached as + -- the First_Index/Next_Index again by the code that also + -- handles non-null aggregates. + + Remove (Aggr_Range (J)); + end loop; + end; + else + Collect_Aggr_Bounds (N, 1); + end if; -- Build the list of constrained indexes of our aggregate itype @@ -1203,9 +1218,6 @@ package body Sem_Aggr is Aggr_Subtyp := Any_Composite; - elsif Is_Null_Aggr then - Aggr_Subtyp := Etype (N); - else Aggr_Subtyp := Array_Aggr_Subtype (N, Typ); end if; @@ -1742,17 +1754,15 @@ package body Sem_Aggr is Loc : constant Source_Ptr := Sloc (N); Id : constant Entity_Id := Defining_Identifier (N); - Id_Typ : Entity_Id := Any_Type; - ----------------------- -- Remove_References -- ----------------------- - function Remove_Ref (N : Node_Id) return Traverse_Result; - -- Remove references to the entity Id after analysis, so it can be + function Remove_Reference (N : Node_Id) return Traverse_Result; + -- Remove reference to the entity Id after analysis, so it can be -- properly reanalyzed after construct is expanded into a loop. - function Remove_Ref (N : Node_Id) return Traverse_Result is + function Remove_Reference (N : Node_Id) return Traverse_Result is begin if Nkind (N) = N_Identifier and then Present (Entity (N)) @@ -1763,15 +1773,15 @@ package body Sem_Aggr is end if; Set_Analyzed (N, False); return OK; - end Remove_Ref; + end Remove_Reference; - procedure Remove_References is new Traverse_Proc (Remove_Ref); + procedure Remove_References is new Traverse_Proc (Remove_Reference); -- Local variables Choice : Node_Id; Dummy : Boolean; - Ent : Entity_Id; + Scop : Entity_Id; Expr : Node_Id; -- Start of processing for Resolve_Iterated_Component_Association @@ -1779,37 +1789,29 @@ package body Sem_Aggr is begin Error_Msg_Ada_2022_Feature ("iterated component", Loc); - if Present (Iterator_Specification (N)) then - Analyze (Name (Iterator_Specification (N))); + -- Create a scope in which to introduce an index, to make it visible + -- for the analysis of component expression. - -- We assume that the domain of iteration cannot be overloaded. + Scop := New_Internal_Entity (E_Loop, Current_Scope, Loc, 'L'); + Set_Etype (Scop, Standard_Void_Type); + Set_Parent (Scop, Parent (N)); + Push_Scope (Scop); - declare - Domain : constant Node_Id := Name (Iterator_Specification (N)); - D_Type : constant Entity_Id := Etype (Domain); - Elt : Entity_Id; - begin - if Is_Array_Type (D_Type) then - Id_Typ := Component_Type (D_Type); + -- If there is iterator specification, then its preanalysis will make + -- the index visible. - else - if Has_Aspect (D_Type, Aspect_Iterable) then - Elt := - Get_Iterable_Type_Primitive (D_Type, Name_Element); - if No (Elt) then - Error_Msg_N - ("missing Element primitive for iteration", Domain); - else - Id_Typ := Etype (Elt); - end if; - else - Error_Msg_N ("cannot iterate over", Domain); - end if; - end if; - end; + if Present (Iterator_Specification (N)) then + Preanalyze (Iterator_Specification (N)); + + -- Otherwise, analyze discrete choices and make the index visible else - Id_Typ := Index_Typ; + -- Insert index name into current scope but don't decorate it yet, + -- so that a premature usage of this name in discrete choices will + -- be nicely diagnosed. + + Enter_Name (Id); + Choice := First (Discrete_Choices (N)); while Present (Choice) loop @@ -1835,25 +1837,13 @@ package body Sem_Aggr is Next (Choice); end loop; - end if; - - -- Create a scope in which to introduce an index, which is usually - -- visible in the expression for the component, and needed for its - -- analysis. - - Ent := New_Internal_Entity (E_Loop, Current_Scope, Loc, 'L'); - Set_Etype (Ent, Standard_Void_Type); - Set_Parent (Ent, Parent (N)); - Push_Scope (Ent); - -- Insert and decorate the index variable in the current scope. - -- The expression has to be analyzed once the index variable is - -- directly visible. + -- Decorate the index variable - Enter_Name (Id); - Set_Etype (Id, Id_Typ); - Mutate_Ekind (Id, E_Variable); - Set_Scope (Id, Ent); + Set_Etype (Id, Index_Typ); + Mutate_Ekind (Id, E_Variable); + Set_Scope (Id, Scop); + end if; -- Analyze expression without expansion, to verify legality. -- When generating code, we then remove references to the index @@ -1926,7 +1916,7 @@ package body Sem_Aggr is and then No (Component_Associations (N)) and then not Null_Record_Present (N) then - return False; + return Failure; end if; -- Disable the warning for GNAT Mode to allow for easier transition. @@ -1966,7 +1956,7 @@ package body Sem_Aggr is Error_Msg_N ("mixed iterated component association" & " (RM 4.3.3 (17.1/5))", Assoc); - return False; + return Failure; end if; Next (Assoc); @@ -1985,7 +1975,7 @@ package body Sem_Aggr is Error_Msg_N ("mixed iterated component association" & " (RM 4.3.3 (17.1/5))", Assoc); - return False; + return Failure; end if; Next (Assoc); @@ -3075,7 +3065,8 @@ package body Sem_Aggr is elsif Present (Iterator_Specification (Comp)) then Copy := Copy_Separate_Tree (Iterator_Specification (Comp)); - Id_Name := Chars (Defining_Identifier (Comp)); + Id_Name := + Chars (Defining_Identifier (Iterator_Specification (Comp))); Analyze (Copy); Typ := Etype (Defining_Identifier (Copy)); @@ -3203,7 +3194,7 @@ package body Sem_Aggr is end if; end; - elsif Present (Add_Named_Subp) then + elsif Present (Add_Named_Subp) then declare -- Retrieves types of container, key, and element from the -- specified insertion procedure. @@ -4104,14 +4095,16 @@ package body Sem_Aggr is Loc : constant Source_Ptr := Sloc (N); Typ : constant Entity_Id := Etype (N); - Check : Node_Id; - Decl : Node_Id; Index : Node_Id; Lo, Hi : Node_Id; Constr : constant List_Id := New_List; - Subt : constant Entity_Id := Make_Temporary (Loc, 'S'); begin + -- Attach the list of constraints at the location of the aggregate, so + -- the individual constraints can be analyzed. + + Set_Parent (Constr, N); + -- Create a constrained subtype with null dimensions Index := First_Index (Typ); @@ -4126,40 +4119,14 @@ package body Sem_Aggr is Attribute_Name => Name_Pred, Expressions => New_List (New_Copy_Tree (Lo))); - -- Check that high bound (i.e., low bound predecessor) exists. - -- Fail if low bound is low bound of base subtype (in all cases, - -- including modular). - - Check := - Make_If_Statement (Loc, - Condition => - Make_Op_Le (Loc, New_Copy_Tree (Lo), New_Copy_Tree (Hi)), - Then_Statements => - New_List (Make_Raise_Constraint_Error - (Loc, Reason => CE_Range_Check_Failed))); - - Insert_Action (N, Check); - - Append (Make_Range (Loc, Lo, Hi), Constr); + Append (Make_Range (Loc, New_Copy_Tree (Lo), Hi), Constr); + Analyze_And_Resolve (Last (Constr), Etype (Index)); Index := Next_Index (Index); end loop; - Decl := Make_Subtype_Declaration (Loc, - Defining_Identifier => Subt, - Subtype_Indication => - Make_Subtype_Indication (Loc, - Subtype_Mark => - New_Occurrence_Of (Base_Type (Typ), Loc), - Constraint => - Make_Index_Or_Discriminant_Constraint (Loc, Constr))); - - Insert_Action (N, Decl); - Set_Is_Internal (Subt); - Analyze (Decl); - Set_Etype (N, Subt); Set_Compile_Time_Known_Aggregate (N); - Set_Aggregate_Bounds (N, New_Copy_Tree (First_Index (Etype (N)))); + Set_Aggregate_Bounds (N, First (Constr)); return True; end Resolve_Null_Array_Aggregate; @@ -5067,9 +5034,7 @@ package body Sem_Aggr is -- OTHERS cannot be used. -- Positional and named associations cannot be mixed. - if Present (Component_Associations (N)) - and then Present (First (Component_Associations (N))) - then + if Present (Component_Associations (N)) then declare Assoc : Node_Id; diff --git a/gcc/ada/sem_aggr.ads b/gcc/ada/sem_aggr.ads index 75af8f7..0d305a8 100644 --- a/gcc/ada/sem_aggr.ads +++ b/gcc/ada/sem_aggr.ads @@ -43,6 +43,10 @@ package Sem_Aggr is -- WARNING: There is a matching C declaration of this subprogram in fe.h + function Is_Null_Aggregate (N : Node_Id) return Boolean; + -- Returns True for a "[]" aggregate (an Ada 2022 feature), even after + -- it has been transformed by expansion. Returns False otherwise. + function Is_Null_Array_Aggregate_High_Bound (N : Node_Id) return Boolean; -- Returns True for the high bound of a null array aggregate. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index a64a3cd..4d1644b 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -944,29 +944,6 @@ package body Sem_Ch13 is -- aspect node N for the given type (entity) of the aspect does not -- appear too late according to the rules in RM 13.1(9) and 13.1(10). - procedure Inherit_Delayed_Rep_Aspects (ASN : Node_Id); - -- As discussed in the spec of Aspects (see Aspect_Delay declaration), - -- a derived type can inherit aspects from its parent which have been - -- specified at the time of the derivation using an aspect, as in: - -- - -- type A is range 1 .. 10 - -- with Size => Not_Defined_Yet; - -- .. - -- type B is new A; - -- .. - -- Not_Defined_Yet : constant := 64; - -- - -- In this example, the Size of A is considered to be specified prior - -- to the derivation, and thus inherited, even though the value is not - -- known at the time of derivation. To deal with this, we use two entity - -- flags. The flag Has_Derived_Rep_Aspects is set in the parent type (A - -- here), and then the flag May_Inherit_Delayed_Rep_Aspects is set in - -- the derived type (B here). If this flag is set when the derived type - -- is frozen, then this procedure is called to ensure proper inheritance - -- of all delayed aspects from the parent type. The derived type is E, - -- the argument to Analyze_Aspects_At_Freeze_Point. ASN is the first - -- aspect specification node in the Rep_Item chain for the parent type. - procedure Make_Pragma_From_Boolean_Aspect (ASN : Node_Id); -- Given an aspect specification node ASN whose expression is an -- optional Boolean, this routines creates the corresponding pragma @@ -1084,199 +1061,6 @@ package body Sem_Ch13 is end if; end Check_Aspect_Too_Late; - --------------------------------- - -- Inherit_Delayed_Rep_Aspects -- - --------------------------------- - - procedure Inherit_Delayed_Rep_Aspects (ASN : Node_Id) is - A_Id : constant Aspect_Id := Get_Aspect_Id (ASN); - P : constant Entity_Id := Entity (ASN); - -- Entity for parent type - - N : Node_Id; - -- Item from Rep_Item chain - - A : Aspect_Id; - - begin - -- Loop through delayed aspects for the parent type - - N := ASN; - while Present (N) loop - if Nkind (N) = N_Aspect_Specification then - exit when Entity (N) /= P; - - if Is_Delayed_Aspect (N) then - A := Get_Aspect_Id (Chars (Identifier (N))); - - -- Process delayed rep aspect. For Boolean attributes it is - -- not possible to cancel an attribute once set (the attempt - -- to use an aspect with xxx => False is an error) for a - -- derived type. So for those cases, we do not have to check - -- if a clause has been given for the derived type, since it - -- is harmless to set it again if it is already set. - - case A is - - -- Alignment - - when Aspect_Alignment => - if not Has_Alignment_Clause (E) then - Set_Alignment (E, Alignment (P)); - end if; - - -- Atomic - - when Aspect_Atomic => - if Is_Atomic (P) then - Set_Is_Atomic (E); - end if; - - -- Atomic_Components - - when Aspect_Atomic_Components => - if Has_Atomic_Components (P) then - Set_Has_Atomic_Components (Base_Type (E)); - end if; - - -- Bit_Order - - when Aspect_Bit_Order => - if Is_Record_Type (E) - and then No (Get_Attribute_Definition_Clause - (E, Attribute_Bit_Order)) - and then Reverse_Bit_Order (P) - then - Set_Reverse_Bit_Order (Base_Type (E)); - end if; - - -- Component_Size - - when Aspect_Component_Size => - if Is_Array_Type (E) - and then not Has_Component_Size_Clause (E) - then - Set_Component_Size - (Base_Type (E), Component_Size (P)); - end if; - - -- Machine_Radix - - when Aspect_Machine_Radix => - if Is_Decimal_Fixed_Point_Type (E) - and then not Has_Machine_Radix_Clause (E) - then - Set_Machine_Radix_10 (E, Machine_Radix_10 (P)); - end if; - - -- Object_Size (also Size which also sets Object_Size) - - when Aspect_Object_Size - | Aspect_Size - => - if not Has_Size_Clause (E) - and then - No (Get_Attribute_Definition_Clause - (E, Attribute_Object_Size)) - then - Set_Esize (E, Esize (P)); - end if; - - -- Pack - - when Aspect_Pack => - if not Is_Packed (E) then - Set_Is_Packed (Base_Type (E)); - - if Is_Bit_Packed_Array (P) then - Set_Is_Bit_Packed_Array (Base_Type (E)); - Set_Packed_Array_Impl_Type - (E, Packed_Array_Impl_Type (P)); - end if; - end if; - - -- Scalar_Storage_Order - - when Aspect_Scalar_Storage_Order => - if (Is_Record_Type (E) or else Is_Array_Type (E)) - and then No (Get_Attribute_Definition_Clause - (E, Attribute_Scalar_Storage_Order)) - and then Reverse_Storage_Order (P) - then - Set_Reverse_Storage_Order (Base_Type (E)); - - -- Clear default SSO indications, since the aspect - -- overrides the default. - - Set_SSO_Set_Low_By_Default (Base_Type (E), False); - Set_SSO_Set_High_By_Default (Base_Type (E), False); - end if; - - -- Small - - when Aspect_Small => - if Is_Fixed_Point_Type (E) - and then not Has_Small_Clause (E) - then - Set_Small_Value (E, Small_Value (P)); - end if; - - -- Storage_Size - - when Aspect_Storage_Size => - if (Is_Access_Type (E) or else Is_Task_Type (E)) - and then not Has_Storage_Size_Clause (E) - then - Set_Storage_Size_Variable - (Base_Type (E), Storage_Size_Variable (P)); - end if; - - -- Value_Size - - when Aspect_Value_Size => - - -- Value_Size is never inherited, it is either set by - -- default, or it is explicitly set for the derived - -- type. So nothing to do here. - - null; - - -- Volatile - - when Aspect_Volatile => - if Is_Volatile (P) then - Set_Is_Volatile (E); - end if; - - -- Volatile_Full_Access (also Full_Access_Only) - - when Aspect_Volatile_Full_Access - | Aspect_Full_Access_Only - => - if Is_Volatile_Full_Access (P) then - Set_Is_Volatile_Full_Access (E); - end if; - - -- Volatile_Components - - when Aspect_Volatile_Components => - if Has_Volatile_Components (P) then - Set_Has_Volatile_Components (Base_Type (E)); - end if; - - -- That should be all the Rep Aspects - - when others => - pragma Assert (Aspect_Delay (A_Id) /= Rep_Aspect); - null; - end case; - end if; - end if; - - Next_Rep_Item (N); - end loop; - end Inherit_Delayed_Rep_Aspects; - ------------------------------------- -- Make_Pragma_From_Boolean_Aspect -- ------------------------------------- @@ -1600,15 +1384,6 @@ package body Sem_Ch13 is Next_Rep_Item (ASN); end loop; - -- This is where we inherit delayed rep aspects from our parent. Note - -- that if we fell out of the above loop with ASN non-empty, it means - -- we hit an aspect for an entity other than E, and it must be the - -- type from which we were derived. - - if May_Inherit_Delayed_Rep_Aspects (E) then - Inherit_Delayed_Rep_Aspects (ASN); - end if; - if In_Instance and then E /= Base_Type (E) and then Is_First_Subtype (E) @@ -13126,139 +12901,6 @@ package body Sem_Ch13 is Inside_Freezing_Actions := Inside_Freezing_Actions - 1; - -- If we have a type with predicates, build predicate function. This is - -- not needed in the generic case, nor within e.g. TSS subprograms and - -- other predefined primitives. For a derived type, ensure that the - -- parent type is already frozen so that its predicate function has been - -- constructed already. This is necessary if the parent is declared - -- in a nested package and its own freeze point has not been reached. - - if Is_Type (E) - and then Nongeneric_Case - and then Has_Predicates (E) - and then Predicate_Check_In_Scope (N) - then - declare - Atyp : constant Entity_Id := Nearest_Ancestor (E); - begin - if Present (Atyp) - and then Has_Predicates (Atyp) - and then not Is_Frozen (Atyp) - then - Freeze_Before (N, Atyp); - end if; - end; - - -- Before we build a predicate function, ensure that discriminant - -- checking functions are available. The predicate function might - -- need to call these functions if the predicate references - -- any components declared in a variant part. - if Ekind (E) = E_Record_Type and then Has_Discriminants (E) then - Build_Or_Copy_Discr_Checking_Funcs (Parent (E)); - end if; - - Build_Predicate_Function (E, N); - end if; - - -- If type has delayed aspects, this is where we do the preanalysis at - -- the freeze point, as part of the consistent visibility check. Note - -- that this must be done after calling Build_Predicate_Function or - -- Build_Invariant_Procedure since these subprograms fix occurrences of - -- the subtype name in the saved expression so that they will not cause - -- trouble in the preanalysis. - - -- This is also not needed in the generic case - - if Nongeneric_Case - and then Has_Delayed_Aspects (E) - and then Scope (E) = Current_Scope - then - declare - Ritem : Node_Id; - - begin - -- Look for aspect specification entries for this entity - - Ritem := First_Rep_Item (E); - while Present (Ritem) loop - if Nkind (Ritem) = N_Aspect_Specification - and then Entity (Ritem) = E - and then Is_Delayed_Aspect (Ritem) - then - if Get_Aspect_Id (Ritem) in Aspect_CPU - | Aspect_Dynamic_Predicate - | Aspect_Predicate - | Aspect_Static_Predicate - | Aspect_Priority - then - -- Retrieve the visibility to components and discriminants - -- in order to properly analyze the aspects. - - Push_Type (E); - Check_Aspect_At_Freeze_Point (Ritem); - - -- In the case of predicate aspects, there will be - -- a corresponding Predicate pragma associated with - -- the aspect, and the expression of the pragma also - -- needs to be analyzed at this point, to ensure that - -- Save_Global_References will capture global refs in - -- expressions that occur in generic bodies, for proper - -- later resolution of the pragma in instantiations. - - if Is_Type (E) - and then Inside_A_Generic - and then Has_Predicates (E) - and then Present (Aspect_Rep_Item (Ritem)) - then - declare - Pragma_Args : constant List_Id := - Pragma_Argument_Associations - (Aspect_Rep_Item (Ritem)); - Pragma_Expr : constant Node_Id := - Expression (Next (First (Pragma_Args))); - begin - if Present (Pragma_Expr) then - Analyze_And_Resolve - (Pragma_Expr, Standard_Boolean); - end if; - end; - end if; - - Pop_Type (E); - - else - Check_Aspect_At_Freeze_Point (Ritem); - end if; - - -- A pragma Predicate should be checked like one of the - -- corresponding aspects, wrt possible misuse of ghost - -- entities. - - elsif Nkind (Ritem) = N_Pragma - and then No (Corresponding_Aspect (Ritem)) - and then - Get_Pragma_Id (Pragma_Name (Ritem)) = Pragma_Predicate - then - -- Retrieve the visibility to components and discriminants - -- in order to properly analyze the pragma. - - declare - Arg : constant Node_Id := - Next (First (Pragma_Argument_Associations (Ritem))); - begin - Push_Type (E); - Preanalyze_Spec_Expression - (Expression (Arg), Standard_Boolean); - Pop_Type (E); - end; - end if; - - Next_Rep_Item (Ritem); - end loop; - end; - - end if; - -- For a record type, deal with variant parts. This has to be delayed to -- this point, because of the issue of statically predicated subtypes, -- which we have to ensure are frozen before checking choices, since we @@ -13424,6 +13066,140 @@ package body Sem_Ch13 is end Check_Variant_Part; end if; + -- If we have a type with predicates, build predicate function. This is + -- not needed in the generic case, nor within e.g. TSS subprograms and + -- other predefined primitives. For a derived type, ensure that the + -- parent type is already frozen so that its predicate function has been + -- constructed already. This is necessary if the parent is declared + -- in a nested package and its own freeze point has not been reached. + + if Is_Type (E) + and then Nongeneric_Case + and then Has_Predicates (E) + and then Predicate_Check_In_Scope (N) + then + declare + Atyp : constant Entity_Id := Nearest_Ancestor (E); + + begin + if Present (Atyp) + and then Has_Predicates (Atyp) + and then not Is_Frozen (Atyp) + then + Freeze_Before (N, Atyp); + end if; + end; + + -- Before we build a predicate function, ensure that discriminant + -- checking functions are available. The predicate function might + -- need to call these functions if the predicate references any + -- components declared in a variant part. + + if Ekind (E) = E_Record_Type and then Has_Discriminants (E) then + Build_Or_Copy_Discr_Checking_Funcs (Parent (E)); + end if; + + Build_Predicate_Function (E, N); + end if; + + -- If type has delayed aspects, this is where we do the preanalysis at + -- the freeze point, as part of the consistent visibility check. Note + -- that this must be done after calling Build_Predicate_Function or + -- Build_Invariant_Procedure since these subprograms fix occurrences of + -- the subtype name in the saved expression so that they will not cause + -- trouble in the preanalysis. + + -- This is also not needed in the generic case + + if Nongeneric_Case + and then Has_Delayed_Aspects (E) + and then Scope (E) = Current_Scope + then + declare + Ritem : Node_Id; + + begin + -- Look for aspect specification entries for this entity + + Ritem := First_Rep_Item (E); + while Present (Ritem) loop + if Nkind (Ritem) = N_Aspect_Specification + and then Entity (Ritem) = E + and then Is_Delayed_Aspect (Ritem) + then + if Get_Aspect_Id (Ritem) in Aspect_CPU + | Aspect_Dynamic_Predicate + | Aspect_Predicate + | Aspect_Static_Predicate + | Aspect_Priority + then + -- Retrieve the visibility to components and discriminants + -- in order to properly analyze the aspects. + + Push_Type (E); + Check_Aspect_At_Freeze_Point (Ritem); + + -- In the case of predicate aspects, there will be + -- a corresponding Predicate pragma associated with + -- the aspect, and the expression of the pragma also + -- needs to be analyzed at this point, to ensure that + -- Save_Global_References will capture global refs in + -- expressions that occur in generic bodies, for proper + -- later resolution of the pragma in instantiations. + + if Is_Type (E) + and then Inside_A_Generic + and then Has_Predicates (E) + and then Present (Aspect_Rep_Item (Ritem)) + then + declare + Pragma_Args : constant List_Id := + Pragma_Argument_Associations + (Aspect_Rep_Item (Ritem)); + Pragma_Expr : constant Node_Id := + Expression (Next (First (Pragma_Args))); + begin + if Present (Pragma_Expr) then + Analyze_And_Resolve + (Pragma_Expr, Standard_Boolean); + end if; + end; + end if; + + Pop_Type (E); + + else + Check_Aspect_At_Freeze_Point (Ritem); + end if; + + -- A pragma Predicate should be checked like one of the + -- corresponding aspects, wrt possible misuse of ghost + -- entities. + + elsif Nkind (Ritem) = N_Pragma + and then No (Corresponding_Aspect (Ritem)) + and then + Get_Pragma_Id (Pragma_Name (Ritem)) = Pragma_Predicate + then + -- Retrieve the visibility to components and discriminants + -- in order to properly analyze the pragma. + + declare + Arg : constant Node_Id := + Next (First (Pragma_Argument_Associations (Ritem))); + begin + Push_Type (E); + Preanalyze_Spec_Expression + (Expression (Arg), Standard_Boolean); + Pop_Type (E); + end; + end if; + + Next_Rep_Item (Ritem); + end loop; + end; + end if; + if not In_Generic_Scope (E) and then Ekind (E) = E_Record_Type and then Is_Tagged_Type (E) @@ -13738,14 +13514,6 @@ package body Sem_Ch13 is -- representation aspect in the rep item chain of Typ, if any, isn't -- directly specified to Typ but to one of its parents. - -- ??? Note that, for now, just a limited number of representation - -- aspects have been inherited here so far. Many of them are - -- still inherited in Sem_Ch3. This will be fixed soon. Here is - -- a non- exhaustive list of aspects that likely also need to - -- be moved to this routine: Alignment, Component_Alignment, - -- Component_Size, Machine_Radix, Object_Size, Pack, Predicates, - -- Preelaborable_Initialization, RM_Size and Small. - -- In addition, Convention must be propagated from base type to subtype, -- because the subtype may have been declared on an incomplete view. @@ -13813,9 +13581,21 @@ package body Sem_Ch13 is and then not Has_Rep_Item (Typ, Name_Default_Component_Value, False) and then Has_Rep_Item (Typ, Name_Default_Component_Value) then - Set_Default_Aspect_Component_Value (Typ, - Default_Aspect_Component_Value - (Entity (Get_Rep_Item (Typ, Name_Default_Component_Value)))); + declare + E : Entity_Id; + + begin + E := Entity (Get_Rep_Item (Typ, Name_Default_Component_Value)); + + -- Deal with private types + + if Is_Private_Type (E) then + E := Full_View (E); + end if; + + Set_Default_Aspect_Component_Value (Typ, + Default_Aspect_Component_Value (E)); + end; end if; -- Default_Value @@ -13826,9 +13606,21 @@ package body Sem_Ch13 is and then Has_Rep_Item (Typ, Name_Default_Value) then Set_Has_Default_Aspect (Typ); - Set_Default_Aspect_Value (Typ, - Default_Aspect_Value - (Entity (Get_Rep_Item (Typ, Name_Default_Value)))); + + declare + E : Entity_Id; + + begin + E := Entity (Get_Rep_Item (Typ, Name_Default_Value)); + + -- Deal with private types + + if Is_Private_Type (E) then + E := Full_View (E); + end if; + + Set_Default_Aspect_Value (Typ, Default_Aspect_Value (E)); + end; end if; -- Discard_Names @@ -13956,6 +13748,209 @@ package body Sem_Ch13 is end if; end Inherit_Aspects_At_Freeze_Point; + --------------------------------- + -- Inherit_Delayed_Rep_Aspects -- + --------------------------------- + + procedure Inherit_Delayed_Rep_Aspects (Typ : Entity_Id) is + A : Aspect_Id; + N : Node_Id; + P : Entity_Id; + + begin + -- Find the first aspect that has been inherited + + N := First_Rep_Item (Typ); + while Present (N) loop + if Nkind (N) = N_Aspect_Specification then + exit when Entity (N) /= Typ; + end if; + + Next_Rep_Item (N); + end loop; + + -- There must be one if we reach here + + pragma Assert (Present (N)); + P := Entity (N); + + -- Loop through delayed aspects for the parent type + + while Present (N) loop + if Nkind (N) = N_Aspect_Specification then + exit when Entity (N) /= P; + + if Is_Delayed_Aspect (N) then + A := Get_Aspect_Id (N); + + -- Process delayed rep aspect. For Boolean attributes it is + -- not possible to cancel an attribute once set (the attempt + -- to use an aspect with xxx => False is an error) for a + -- derived type. So for those cases, we do not have to check + -- if a clause has been given for the derived type, since it + -- is harmless to set it again if it is already set. + + case A is + + -- Alignment + + when Aspect_Alignment => + if not Has_Alignment_Clause (Typ) then + Set_Alignment (Typ, Alignment (P)); + end if; + + -- Atomic + + when Aspect_Atomic => + if Is_Atomic (P) then + Set_Is_Atomic (Typ); + end if; + + -- Atomic_Components + + when Aspect_Atomic_Components => + if Has_Atomic_Components (P) then + Set_Has_Atomic_Components (Base_Type (Typ)); + end if; + + -- Bit_Order + + when Aspect_Bit_Order => + if Is_Record_Type (Typ) + and then No (Get_Attribute_Definition_Clause + (Typ, Attribute_Bit_Order)) + and then Reverse_Bit_Order (P) + then + Set_Reverse_Bit_Order (Base_Type (Typ)); + end if; + + -- Component_Size + + when Aspect_Component_Size => + if Is_Array_Type (Typ) + and then not Has_Component_Size_Clause (Typ) + then + Set_Component_Size + (Base_Type (Typ), Component_Size (P)); + end if; + + -- Machine_Radix + + when Aspect_Machine_Radix => + if Is_Decimal_Fixed_Point_Type (Typ) + and then not Has_Machine_Radix_Clause (Typ) + then + Set_Machine_Radix_10 (Typ, Machine_Radix_10 (P)); + end if; + + -- Object_Size (also Size which also sets Object_Size) + + when Aspect_Object_Size + | Aspect_Size + => + if not Has_Size_Clause (Typ) + and then + No (Get_Attribute_Definition_Clause + (Typ, Attribute_Object_Size)) + then + Set_Esize (Typ, Esize (P)); + end if; + + -- Pack + + when Aspect_Pack => + if not Is_Packed (Typ) then + Set_Is_Packed (Base_Type (Typ)); + + if Is_Bit_Packed_Array (P) then + Set_Is_Bit_Packed_Array (Base_Type (Typ)); + Set_Packed_Array_Impl_Type + (Typ, Packed_Array_Impl_Type (P)); + end if; + end if; + + -- Scalar_Storage_Order + + when Aspect_Scalar_Storage_Order => + if (Is_Record_Type (Typ) or else Is_Array_Type (Typ)) + and then No (Get_Attribute_Definition_Clause + (Typ, Attribute_Scalar_Storage_Order)) + and then Reverse_Storage_Order (P) + then + Set_Reverse_Storage_Order (Base_Type (Typ)); + + -- Clear default SSO indications, since the aspect + -- overrides the default. + + Set_SSO_Set_Low_By_Default (Base_Type (Typ), False); + Set_SSO_Set_High_By_Default (Base_Type (Typ), False); + end if; + + -- Small + + when Aspect_Small => + if Is_Fixed_Point_Type (Typ) + and then not Has_Small_Clause (Typ) + then + Set_Small_Value (Typ, Small_Value (P)); + end if; + + -- Storage_Size + + when Aspect_Storage_Size => + if (Is_Access_Type (Typ) or else Is_Task_Type (Typ)) + and then not Has_Storage_Size_Clause (Typ) + then + Set_Storage_Size_Variable + (Base_Type (Typ), Storage_Size_Variable (P)); + end if; + + -- Value_Size + + when Aspect_Value_Size => + + -- Value_Size is never inherited, it is either set by + -- default, or it is explicitly set for the derived + -- type. So nothing to do here. + + null; + + -- Volatile + + when Aspect_Volatile => + if Is_Volatile (P) then + Set_Is_Volatile (Typ); + end if; + + -- Volatile_Full_Access (also Full_Access_Only) + + when Aspect_Volatile_Full_Access + | Aspect_Full_Access_Only + => + if Is_Volatile_Full_Access (P) then + Set_Is_Volatile_Full_Access (Typ); + end if; + + -- Volatile_Components + + when Aspect_Volatile_Components => + if Has_Volatile_Components (P) then + Set_Has_Volatile_Components (Base_Type (Typ)); + end if; + + -- That should be all the Rep Aspects + + when others => + pragma Assert (Aspect_Delay (A) /= Rep_Aspect); + null; + end case; + end if; + end if; + + Next_Rep_Item (N); + end loop; + end Inherit_Delayed_Rep_Aspects; + ---------------- -- Initialize -- ---------------- @@ -17731,7 +17726,9 @@ package body Sem_Ch13 is begin -- Skip if function marked as warnings off - if Warnings_Off (Act_Unit) or else Serious_Errors_Detected > 0 then + if Has_Warnings_Off (Act_Unit) + or else Serious_Errors_Detected > 0 + then goto Continue; end if; diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads index e0d84c9..1405f89 100644 --- a/gcc/ada/sem_ch13.ads +++ b/gcc/ada/sem_ch13.ads @@ -324,6 +324,36 @@ package Sem_Ch13 is -- Given an entity Typ that denotes a derived type or a subtype, this -- routine performs the inheritance of aspects at the freeze point. + -- ??? Note that, for now, just a limited number of representation aspects + -- have been inherited here so far. Many of them are still inherited in + -- Sem_Ch3 and need to be dealt with. Here is a non-exhaustive list of + -- aspects that likely also need to be moved to this routine: Alignment, + -- Component_Alignment, Component_Size, Machine_Radix, Object_Size, Pack, + -- Predicates, Preelaborable_Initialization, Size and Small. + + procedure Inherit_Delayed_Rep_Aspects (Typ : Entity_Id); + -- As discussed in the spec of Aspects (see Aspect_Delay declaration), + -- a derived type can inherit aspects from its parent which have been + -- specified at the time of the derivation using an aspect, as in: + -- + -- type A is range 1 .. 10 + -- with Size => Not_Defined_Yet; + -- .. + -- type B is new A; + -- .. + -- Not_Defined_Yet : constant := 64; + -- + -- In this example, the Size of A is considered to be specified prior + -- to the derivation, and thus inherited, even though the value is not + -- known at the time of derivation. To deal with this, we use two entity + -- flags. The flag Has_Derived_Rep_Aspects is set in the parent type (A + -- here), and then the flag May_Inherit_Delayed_Rep_Aspects is set in + -- the derived type (B here). If this flag is set when the derived type + -- is frozen, then this procedure is called to ensure proper inheritance + -- of all delayed aspects from the parent type. + + -- ??? Obviously we ought not to have two mechanisms to do the same thing + procedure Resolve_Aspect_Expressions (E : Entity_Id); -- Name resolution of an aspect expression happens at the end of the -- current declarative part or at the freeze point for the entity, diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 790d1d1..00c2e67 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -4770,20 +4770,13 @@ package body Sem_Ch3 is if not Is_Entity_Name (Object_Definition (N)) then Act_T := Etype (E); Check_Compile_Time_Size (Act_T); - - if Aliased_Present (N) then - Set_Is_Constr_Subt_For_UN_Aliased (Act_T); - end if; end if; -- When the given object definition and the aggregate are specified -- independently, and their lengths might differ do a length check. -- This cannot happen if the aggregate is of the form (others =>...) - if not Is_Constrained (T) then - null; - - elsif Nkind (E) = N_Raise_Constraint_Error then + if Nkind (E) = N_Raise_Constraint_Error then -- Aggregate is statically illegal. Place back in declaration @@ -7419,12 +7412,13 @@ package body Sem_Ch3 is Analyze (High_Bound (Range_Expression (Constraint (Indic)))); end if; - -- Introduce an implicit base type for the derived type even if there + -- Create an implicit base type for the derived type even if there -- is no constraint attached to it, since this seems closer to the - -- Ada semantics. Build a full type declaration tree for the derived - -- type using the implicit base type as the defining identifier. Then - -- build a subtype declaration tree which applies the constraint (if - -- any) have it replace the derived type declaration. + -- Ada semantics. Use an Itype like for the implicit base type of + -- other kinds of derived type, but build a full type declaration + -- for it so as to analyze the new literals properly. Then build a + -- subtype declaration tree which applies the constraint (if any) + -- and have it replace the derived type declaration. Literal := First_Literal (Parent_Type); Literals_List := New_List; @@ -7457,8 +7451,7 @@ package body Sem_Ch3 is end loop; Implicit_Base := - Make_Defining_Identifier (Sloc (Derived_Type), - Chars => New_External_Name (Chars (Derived_Type), 'B')); + Create_Itype (E_Enumeration_Type, N, Derived_Type, 'B'); -- Indicate the proper nature of the derived type. This must be done -- before analysis of the literals, to recognize cases when a literal @@ -7471,12 +7464,12 @@ package body Sem_Ch3 is Type_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => Implicit_Base, - Discriminant_Specifications => No_List, Type_Definition => Make_Enumeration_Type_Definition (Loc, Literals_List)); - Mark_Rewrite_Insertion (Type_Decl); - Insert_Before (N, Type_Decl); + -- Do not insert the declarationn, just analyze it in the context + + Set_Parent (Type_Decl, Parent (N)); Analyze (Type_Decl); -- The anonymous base now has a full declaration, but this base @@ -7777,35 +7770,6 @@ package body Sem_Ch3 is -- must be converted to the derived type. Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc); - - -- The implicit_base should be frozen when the derived type is frozen, - -- but note that it is used in the conversions of the bounds. For fixed - -- types we delay the determination of the bounds until the proper - -- freezing point. For other numeric types this is rejected by GCC, for - -- reasons that are currently unclear (???), so we choose to freeze the - -- implicit base now. In the case of integers and floating point types - -- this is harmless because subsequent representation clauses cannot - -- affect anything, but it is still baffling that we cannot use the - -- same mechanism for all derived numeric types. - - -- There is a further complication: actually some representation - -- clauses can affect the implicit base type. For example, attribute - -- definition clauses for stream-oriented attributes need to set the - -- corresponding TSS entries on the base type, and this normally - -- cannot be done after the base type is frozen, so the circuitry in - -- Sem_Ch13.New_Stream_Subprogram must account for this possibility - -- and not use Set_TSS in this case. - - -- There are also consequences for the case of delayed representation - -- aspects for some cases. For example, a Size aspect is delayed and - -- should not be evaluated to the freeze point. This early freezing - -- means that the size attribute evaluation happens too early??? - - if Is_Fixed_Point_Type (Parent_Type) then - Conditional_Delay (Implicit_Base, Parent_Type); - else - Freeze_Before (N, Implicit_Base); - end if; end Build_Derived_Numeric_Type; -------------------------------- @@ -14450,14 +14414,18 @@ package body Sem_Ch3 is begin Mutate_Ekind (Def_Id, E_Enumeration_Subtype); - Set_First_Literal (Def_Id, First_Literal (Base_Type (T))); + Set_First_Literal (Def_Id, First_Literal (Base_Type (T))); + Set_Etype (Def_Id, Base_Type (T)); + Set_Size_Info (Def_Id, (T)); + Set_Is_Character_Type (Def_Id, Is_Character_Type (T)); + Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); - Set_Etype (Def_Id, Base_Type (T)); - Set_Size_Info (Def_Id, (T)); - Set_First_Rep_Item (Def_Id, First_Rep_Item (T)); - Set_Is_Character_Type (Def_Id, Is_Character_Type (T)); + -- Inherit the chain of representation items instead of replacing it + -- because Build_Derived_Enumeration_Type rewrites the declaration of + -- the derived type as a subtype declaration and the former needs to + -- preserve existing representation items (see Build_Derived_Type). - Set_Scalar_Range_For_Subtype (Def_Id, Range_Expression (C), T); + Inherit_Rep_Item_Chain (Def_Id, T); Set_Discrete_RM_Size (Def_Id); end Constrain_Enumeration; @@ -16999,11 +16967,9 @@ package body Sem_Ch3 is Low_Bound => Lo, High_Bound => Hi)); - Conditional_Delay (Derived_Type, Parent_Type); - - Mutate_Ekind (Derived_Type, E_Enumeration_Subtype); - Set_Etype (Derived_Type, Implicit_Base); - Set_Size_Info (Derived_Type, Parent_Type); + Mutate_Ekind (Derived_Type, E_Enumeration_Subtype); + Set_Etype (Derived_Type, Implicit_Base); + Set_Size_Info (Derived_Type, Parent_Type); if not Known_RM_Size (Derived_Type) then Set_RM_Size (Derived_Type, RM_Size (Parent_Type)); @@ -17022,16 +16988,6 @@ package body Sem_Ch3 is end if; Convert_Scalar_Bounds (N, Parent_Type, Derived_Type, Loc); - - -- Because the implicit base is used in the conversion of the bounds, we - -- have to freeze it now. This is similar to what is done for numeric - -- types, and it equally suspicious, but otherwise a nonstatic bound - -- will have a reference to an unfrozen type, which is rejected by Gigi - -- (???). This requires specific care for definition of stream - -- attributes. For details, see comments at the end of - -- Build_Derived_Numeric_Type. - - Freeze_Before (N, Implicit_Base); end Derived_Standard_Character; ------------------------------ diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 5497483..ed2f621c 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -4394,9 +4394,8 @@ package body Sem_Ch4 is procedure Analyze_Quantified_Expression (N : Node_Id) is function Is_Empty_Range (Typ : Entity_Id) return Boolean; - -- If the iterator is part of a quantified expression, and the range is - -- known to be statically empty, emit a warning and replace expression - -- with its static value. Returns True if the replacement occurs. + -- Return True if the iterator is part of a quantified expression and + -- the range is known to be statically empty. function No_Else_Or_Trivial_True (If_Expr : Node_Id) return Boolean; -- Determine whether if expression If_Expr lacks an else part or if it @@ -4407,36 +4406,12 @@ package body Sem_Ch4 is -------------------- function Is_Empty_Range (Typ : Entity_Id) return Boolean is - Loc : constant Source_Ptr := Sloc (N); - begin - if Is_Array_Type (Typ) + return Is_Array_Type (Typ) and then Compile_Time_Known_Bounds (Typ) and then - (Expr_Value (Type_Low_Bound (Etype (First_Index (Typ)))) > - Expr_Value (Type_High_Bound (Etype (First_Index (Typ))))) - then - Preanalyze_And_Resolve (Condition (N), Standard_Boolean); - - if All_Present (N) then - Error_Msg_N - ("??quantified expression with ALL " - & "over a null range has value True", N); - Rewrite (N, New_Occurrence_Of (Standard_True, Loc)); - - else - Error_Msg_N - ("??quantified expression with SOME " - & "over a null range has value False", N); - Rewrite (N, New_Occurrence_Of (Standard_False, Loc)); - end if; - - Analyze (N); - return True; - - else - return False; - end if; + Expr_Value (Type_Low_Bound (Etype (First_Index (Typ)))) > + Expr_Value (Type_High_Bound (Etype (First_Index (Typ)))); end Is_Empty_Range; ----------------------------- @@ -4456,6 +4431,7 @@ package body Sem_Ch4 is -- Local variables Cond : constant Node_Id := Condition (N); + Loc : constant Source_Ptr := Sloc (N); Loop_Id : Entity_Id; QE_Scop : Entity_Id; @@ -4466,7 +4442,7 @@ package body Sem_Ch4 is -- expression. The scope is needed to provide proper visibility of the -- loop variable. - QE_Scop := New_Internal_Entity (E_Loop, Current_Scope, Sloc (N), 'L'); + QE_Scop := New_Internal_Entity (E_Loop, Current_Scope, Loc, 'L'); Set_Etype (QE_Scop, Standard_Void_Type); Set_Scope (QE_Scop, Current_Scope); Set_Parent (QE_Scop, N); @@ -4482,11 +4458,30 @@ package body Sem_Ch4 is Preanalyze (Iterator_Specification (N)); -- Do not proceed with the analysis when the range of iteration is - -- empty. The appropriate error is issued by Is_Empty_Range. + -- empty. if Is_Entity_Name (Name (Iterator_Specification (N))) and then Is_Empty_Range (Etype (Name (Iterator_Specification (N)))) then + Preanalyze_And_Resolve (Condition (N), Standard_Boolean); + End_Scope; + + -- Emit a warning and replace expression with its static value + + if All_Present (N) then + Error_Msg_N + ("??quantified expression with ALL " + & "over a null range has value True", N); + Rewrite (N, New_Occurrence_Of (Standard_True, Loc)); + + else + Error_Msg_N + ("??quantified expression with SOME " + & "over a null range has value False", N); + Rewrite (N, New_Occurrence_Of (Standard_False, Loc)); + end if; + + Analyze (N); return; end if; diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index e1b5722..17bf6d9 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -2211,7 +2211,7 @@ package body Sem_Ch5 is procedure Check_Subtype_Definition (Comp_Type : Entity_Id) is begin - if not Present (Subt) then + if No (Subt) then return; end if; @@ -2231,9 +2231,8 @@ package body Sem_Ch5 is Subt, Comp_Type); end if; - elsif Present (Subt) - and then (not Covers (Base_Type (Bas), Comp_Type) - or else not Subtypes_Statically_Match (Bas, Comp_Type)) + elsif not Covers (Base_Type (Bas), Comp_Type) + or else not Subtypes_Statically_Match (Bas, Comp_Type) then if Is_Array_Type (Typ) then Error_Msg_NE @@ -2330,7 +2329,7 @@ package body Sem_Ch5 is Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => S, - Type_Definition => + Type_Definition => New_Copy_Tree (Access_To_Subprogram_Definition (Subt))); end if; @@ -3365,9 +3364,7 @@ package body Sem_Ch5 is declare Flist : constant List_Id := Freeze_Entity (Id, N); begin - if Is_Non_Empty_List (Flist) then - Insert_Actions (N, Flist); - end if; + Insert_Actions (N, Flist); end; end if; diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index e4af71c..7240129 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -5409,14 +5409,20 @@ package body Sem_Ch6 is -- we have a special test to set X as apparently assigned to suppress -- the warning. - declare - Stm : Node_Id; + -- If X above is controlled, we need to use First_Real_Statement to skip + -- generated finalization-related code. Otherwise (First_Real_Statement + -- is Empty), we just get the first statement. + declare + Stm : Node_Id := First_Real_Statement (HSS); begin + if No (Stm) then + Stm := First (Statements (HSS)); + end if; + -- Skip call markers installed by the ABE mechanism, labels, and -- Push_xxx_Error_Label to find the first real statement. - Stm := First (Statements (HSS)); while Nkind (Stm) in N_Call_Marker | N_Label | N_Push_xxx_Label loop Next (Stm); end loop; diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index 077c988..b8e3fb6 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -3339,7 +3339,9 @@ package body Sem_Elab is Traverse_List (Else_Actions (Scen)); elsif Nkind (Scen) in - N_Component_Association | N_Iterated_Component_Association + N_Component_Association + | N_Iterated_Component_Association + | N_Iterated_Element_Association then Traverse_List (Loop_Actions (Scen)); @@ -18765,9 +18767,9 @@ package body Sem_Elab is T : constant Entity_Id := Etype (First_Formal (E)); begin if Is_Controlled (T) then - if Warnings_Off (T) + if Has_Warnings_Off (T) or else (Ekind (T) = E_Private_Type - and then Warnings_Off (Full_View (T))) + and then Has_Warnings_Off (Full_View (T))) then goto Output; end if; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 44fc955..f618467 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -3163,9 +3163,21 @@ package body Sem_Res is = N_Iterated_Component_Association and then Is_Boolean_Type (Typ) then - Error_Msg_N -- CODEFIX - ("missing ALL or SOME in quantified expression", - Defining_Identifier (First (Component_Associations (N)))); + if Present + (Iterator_Specification + (First (Component_Associations (N)))) + then + Error_Msg_N -- CODEFIX + ("missing ALL or SOME in quantified expression", + Defining_Identifier + (Iterator_Specification + (First (Component_Associations (N))))); + else + Error_Msg_N -- CODEFIX + ("missing ALL or SOME in quantified expression", + Defining_Identifier + (First (Component_Associations (N)))); + end if; -- For an operator with no interpretation, check whether -- one of its operands may be a user-defined literal. diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 13ffb11..ecfb49a 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -22167,19 +22167,6 @@ package body Sem_Util is pragma Assert (No (Actual)); end Iterate_Call_Parameters; - --------------------------- - -- Itype_Has_Declaration -- - --------------------------- - - function Itype_Has_Declaration (Id : Entity_Id) return Boolean is - begin - pragma Assert (Is_Itype (Id)); - return Present (Parent (Id)) - and then Nkind (Parent (Id)) in - N_Full_Type_Declaration | N_Subtype_Declaration - and then Defining_Entity (Parent (Id)) = Id; - end Itype_Has_Declaration; - ------------------------- -- Kill_Current_Values -- ------------------------- @@ -29500,6 +29487,9 @@ package body Sem_Util is when N_Iterated_Component_Association => Traverse_More (Loop_Actions (Node), Result); + when N_Iterated_Element_Association => + Traverse_More (Loop_Actions (Node), Result); + when N_Iteration_Scheme => Traverse_More (Condition_Actions (Node), Result); diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index dde5b27..9f909e0 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2561,11 +2561,6 @@ package Sem_Util is -- Calls Handle_Parameter for each pair of formal and actual parameters of -- a function, procedure, or entry call. - function Itype_Has_Declaration (Id : Entity_Id) return Boolean; - -- Applies to Itypes. True if the Itype is attached to a declaration for - -- the type through its Parent field, which may or not be present in the - -- tree. - procedure Kill_Current_Values (Last_Assignment_Only : Boolean := False); -- This procedure is called to clear all constant indications from all -- entities in the current scope and in any parent scopes if the current diff --git a/gcc/ada/sigtramp-vxworks-target.h b/gcc/ada/sigtramp-vxworks-target.h index 153426e..3c85aa2 100644 --- a/gcc/ada/sigtramp-vxworks-target.h +++ b/gcc/ada/sigtramp-vxworks-target.h @@ -149,7 +149,7 @@ In general: There is no unique numbering for the x86 architecture. It's parameterized - by DWARF_FRAME_REGNUM, which is DBX_REGISTER_NUMBER except for Windows, and + by DWARF_FRAME_REGNUM, which is DEBUGGER_REGNO except for Windows, and the latter depends on the platform. */ diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index ddac1c9..fddfc72 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -4183,11 +4183,15 @@ package Sinfo is -- ITERATED_COMPONENT_ASSOCIATION ::= -- for DEFINING_IDENTIFIER in DISCRETE_CHOICE_LIST => EXPRESSION + -- for ITERATOR_SPECIFICATION => EXPRESSION + + -- At most one of (Defining_Identifier, Iterator_Specification) + -- is present at a time, in which case the other one is empty. -- N_Iterated_Component_Association -- Sloc points to FOR -- Defining_Identifier - -- Iterator_Specification (set to Empty if no Iterator_Spec) + -- Iterator_Specification -- Expression -- Discrete_Choices -- Loop_Actions @@ -4207,9 +4211,13 @@ package Sinfo is -- Etype --------------------------------- - -- 3.4.5 Comtainer_Aggregates -- + -- 3.4.5 Container_Aggregates -- --------------------------------- + -- ITERATED_ELEMENT_ASSOCIATION ::= + -- for LOOP_PARAMETER_SPECIFICATION[ use KEY_EXPRESSION] => EXPRESSION + -- | for ITERATOR_SPECIFICATION[ use KEY_EXPRESSION] => EXPRESSION + -- N_Iterated_Element_Association -- Key_Expression -- Iterator_Specification diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index 42a6e4f..243d67a 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -1341,9 +1341,13 @@ package body Sprint is when N_Iterated_Component_Association => Set_Debug_Sloc; Write_Str (" for "); - Write_Id (Defining_Identifier (Node)); - Write_Str (" in "); - Sprint_Bar_List (Discrete_Choices (Node)); + if Present (Iterator_Specification (Node)) then + Sprint_Node (Iterator_Specification (Node)); + else + Write_Id (Defining_Identifier (Node)); + Write_Str (" in "); + Sprint_Bar_List (Discrete_Choices (Node)); + end if; Write_Str (" => "); Sprint_Node (Expression (Node)); @@ -2307,6 +2311,11 @@ package body Sprint is Sprint_Node (Name (Node)); + if Present (Iterator_Filter (Node)) then + Write_Str (" when "); + Sprint_Node (Iterator_Filter (Node)); + end if; + when N_Itype_Reference => Write_Indent_Str_Sloc ("reference "); Write_Id (Itype (Node)); diff --git a/gcc/ada/switch-b.adb b/gcc/ada/switch-b.adb index 10feb23..a543ad9 100644 --- a/gcc/ada/switch-b.adb +++ b/gcc/ada/switch-b.adb @@ -379,6 +379,12 @@ package body Switch.B is Bad_Switch (Switch_Chars); end if; + -- Processing for k switch + + when 'k' => + Ptr := Ptr + 1; + Check_Elaboration_Flags := False; + -- Processing for K switch when 'K' => diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb index 32f6e81..a9f4088 100644 --- a/gcc/ada/treepr.adb +++ b/gcc/ada/treepr.adb @@ -135,10 +135,6 @@ package body Treepr is function From_Union is new Ada.Unchecked_Conversion (Union_Id, Uint); function From_Union is new Ada.Unchecked_Conversion (Union_Id, Ureal); - function To_Mixed (S : String) return String; - -- Turns an identifier into Mixed_Case. For bootstrap reasons, we cannot - -- use To_Mixed function from System.Case_Util. - function Image (F : Node_Or_Entity_Field) return String; procedure Print_Init; @@ -371,8 +367,9 @@ package body Treepr is when others => declare - Result : constant String := To_Mixed (F'Img); + Result : String := F'Img; begin + To_Mixed (Result); return Result (3 .. Result'Last); -- Remove "F_" end; end case; @@ -1671,8 +1668,10 @@ package body Treepr is -------------------------- procedure Print_Str_Mixed_Case (S : String) is + Tmp : String := S; begin - Print_Str (To_Mixed (S)); + To_Mixed (Tmp); + Print_Str (Tmp); end Print_Str_Mixed_Case; ---------------- @@ -1806,17 +1805,6 @@ package body Treepr is Next_Serial_Number := Next_Serial_Number + 1; end Set_Serial_Number; - -------------- - -- To_Mixed -- - -------------- - - function To_Mixed (S : String) return String is - begin - return Result : String (S'Range) := S do - To_Mixed (Result); - end return; - end To_Mixed; - --------------- -- Tree_Dump -- --------------- diff --git a/gcc/builtins.cc b/gcc/builtins.cc index b08b436..5f319b2 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -123,6 +123,7 @@ static rtx expand_builtin_fegetround (tree, rtx, machine_mode); static rtx expand_builtin_feclear_feraise_except (tree, rtx, machine_mode, optab); static rtx expand_builtin_cexpi (tree, rtx); +static rtx expand_builtin_issignaling (tree, rtx); static rtx expand_builtin_int_roundingfn (tree, rtx); static rtx expand_builtin_int_roundingfn_2 (tree, rtx); static rtx expand_builtin_next_arg (void); @@ -2747,6 +2748,300 @@ build_call_nofold_loc (location_t loc, tree fndecl, int n, ...) return fn; } +/* Expand the __builtin_issignaling builtin. This needs to handle + all floating point formats that do support NaNs (for those that + don't it just sets target to 0). */ + +static rtx +expand_builtin_issignaling (tree exp, rtx target) +{ + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; + + tree arg = CALL_EXPR_ARG (exp, 0); + scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg)); + const struct real_format *fmt = REAL_MODE_FORMAT (fmode); + + /* Expand the argument yielding a RTX expression. */ + rtx temp = expand_normal (arg); + + /* If mode doesn't support NaN, always return 0. + Don't use !HONOR_SNANS (fmode) here, so there is some possibility of + __builtin_issignaling working without -fsignaling-nans. Especially + when -fno-signaling-nans is the default. + On the other side, MODE_HAS_NANS (fmode) is unnecessary, with + -ffinite-math-only even __builtin_isnan or __builtin_fpclassify + fold to 0 or non-NaN/Inf classification. */ + if (!HONOR_NANS (fmode)) + { + emit_move_insn (target, const0_rtx); + return target; + } + + /* Check if the back end provides an insn that handles issignaling for the + argument's mode. */ + enum insn_code icode = optab_handler (issignaling_optab, fmode); + if (icode != CODE_FOR_nothing) + { + rtx_insn *last = get_last_insn (); + rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN)) + return this_target; + delete_insns_since (last); + } + + if (DECIMAL_FLOAT_MODE_P (fmode)) + { + scalar_int_mode imode; + rtx hi; + switch (fmt->ieee_bits) + { + case 32: + case 64: + imode = int_mode_for_mode (fmode).require (); + temp = gen_lowpart (imode, temp); + break; + case 128: + imode = int_mode_for_size (64, 1).require (); + hi = NULL_RTX; + /* For decimal128, TImode support isn't always there and even when + it is, working on the DImode high part is usually better. */ + if (!MEM_P (temp)) + { + if (rtx t = simplify_gen_subreg (imode, temp, fmode, + subreg_highpart_offset (imode, + fmode))) + hi = t; + else + { + scalar_int_mode imode2; + if (int_mode_for_mode (fmode).exists (&imode2)) + { + rtx temp2 = gen_lowpart (imode2, temp); + poly_uint64 off = subreg_highpart_offset (imode, imode2); + if (rtx t = simplify_gen_subreg (imode, temp2, + imode2, off)) + hi = t; + } + } + if (!hi) + { + rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode)); + emit_move_insn (mem, temp); + temp = mem; + } + } + if (!hi) + { + poly_int64 offset + = subreg_highpart_offset (imode, GET_MODE (temp)); + hi = adjust_address (temp, imode, offset); + } + temp = hi; + break; + default: + gcc_unreachable (); + } + /* In all of decimal{32,64,128}, there is MSB sign bit and sNaN + have 6 bits below it all set. */ + rtx val + = GEN_INT (HOST_WIDE_INT_C (0x3f) << (GET_MODE_BITSIZE (imode) - 7)); + temp = expand_binop (imode, and_optab, temp, val, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, EQ, temp, val, imode, 1, 1); + return temp; + } + + /* Only PDP11 has these defined differently but doesn't support NaNs. */ + gcc_assert (FLOAT_WORDS_BIG_ENDIAN == WORDS_BIG_ENDIAN); + gcc_assert (fmt->signbit_ro > 0 && fmt->b == 2); + gcc_assert (MODE_COMPOSITE_P (fmode) + || (fmt->pnan == fmt->p + && fmt->signbit_ro == fmt->signbit_rw)); + + switch (fmt->p) + { + case 106: /* IBM double double */ + /* For IBM double double, recurse on the most significant double. */ + gcc_assert (MODE_COMPOSITE_P (fmode)); + temp = convert_modes (DFmode, fmode, temp, 0); + fmode = DFmode; + fmt = REAL_MODE_FORMAT (DFmode); + /* FALLTHRU */ + case 8: /* bfloat */ + case 11: /* IEEE half */ + case 24: /* IEEE single */ + case 53: /* IEEE double or Intel extended with rounding to double */ + if (fmt->p == 53 && fmt->signbit_ro == 79) + goto extended; + { + scalar_int_mode imode = int_mode_for_mode (fmode).require (); + temp = gen_lowpart (imode, temp); + rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2)) + & ~(HOST_WIDE_INT_M1U << fmt->signbit_ro)); + if (fmt->qnan_msb_set) + { + rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << fmt->signbit_ro)); + rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2)); + /* For non-MIPS/PA IEEE single/double/half or bfloat, expand to: + ((temp ^ bit) & mask) > val. */ + temp = expand_binop (imode, xor_optab, temp, bit, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (imode, and_optab, temp, mask, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, GTU, temp, val, imode, + 1, 1); + } + else + { + /* For MIPS/PA IEEE single/double, expand to: + (temp & val) == val. */ + temp = expand_binop (imode, and_optab, temp, val, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, EQ, temp, val, imode, + 1, 1); + } + } + break; + case 113: /* IEEE quad */ + { + rtx hi = NULL_RTX, lo = NULL_RTX; + scalar_int_mode imode = int_mode_for_size (64, 1).require (); + /* For IEEE quad, TImode support isn't always there and even when + it is, working on DImode parts is usually better. */ + if (!MEM_P (temp)) + { + hi = simplify_gen_subreg (imode, temp, fmode, + subreg_highpart_offset (imode, fmode)); + lo = simplify_gen_subreg (imode, temp, fmode, + subreg_lowpart_offset (imode, fmode)); + if (!hi || !lo) + { + scalar_int_mode imode2; + if (int_mode_for_mode (fmode).exists (&imode2)) + { + rtx temp2 = gen_lowpart (imode2, temp); + hi = simplify_gen_subreg (imode, temp2, imode2, + subreg_highpart_offset (imode, + imode2)); + lo = simplify_gen_subreg (imode, temp2, imode2, + subreg_lowpart_offset (imode, + imode2)); + } + } + if (!hi || !lo) + { + rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode)); + emit_move_insn (mem, temp); + temp = mem; + } + } + if (!hi || !lo) + { + poly_int64 offset + = subreg_highpart_offset (imode, GET_MODE (temp)); + hi = adjust_address (temp, imode, offset); + offset = subreg_lowpart_offset (imode, GET_MODE (temp)); + lo = adjust_address (temp, imode, offset); + } + rtx val = GEN_INT ((HOST_WIDE_INT_M1U << (fmt->p - 2 - 64)) + & ~(HOST_WIDE_INT_M1U << (fmt->signbit_ro - 64))); + if (fmt->qnan_msb_set) + { + rtx mask = GEN_INT (~(HOST_WIDE_INT_M1U << (fmt->signbit_ro + - 64))); + rtx bit = GEN_INT (HOST_WIDE_INT_1U << (fmt->p - 2 - 64)); + /* For non-MIPS/PA IEEE quad, expand to: + (((hi ^ bit) | ((lo | -lo) >> 63)) & mask) > val. */ + rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0); + lo = expand_binop (imode, ior_optab, lo, nlo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + lo = expand_shift (RSHIFT_EXPR, imode, lo, 63, NULL_RTX, 1); + temp = expand_binop (imode, xor_optab, hi, bit, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (imode, ior_optab, temp, lo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (imode, and_optab, temp, mask, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, GTU, temp, val, imode, + 1, 1); + } + else + { + /* For MIPS/PA IEEE quad, expand to: + (hi & val) == val. */ + temp = expand_binop (imode, and_optab, hi, val, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, EQ, temp, val, imode, + 1, 1); + } + } + break; + case 64: /* Intel or Motorola extended */ + extended: + { + rtx ex, hi, lo; + scalar_int_mode imode = int_mode_for_size (32, 1).require (); + scalar_int_mode iemode = int_mode_for_size (16, 1).require (); + if (!MEM_P (temp)) + { + rtx mem = assign_stack_temp (fmode, GET_MODE_SIZE (fmode)); + emit_move_insn (mem, temp); + temp = mem; + } + if (fmt->signbit_ro == 95) + { + /* Motorola, always big endian, with 16-bit gap in between + 16-bit sign+exponent and 64-bit mantissa. */ + ex = adjust_address (temp, iemode, 0); + hi = adjust_address (temp, imode, 4); + lo = adjust_address (temp, imode, 8); + } + else if (!WORDS_BIG_ENDIAN) + { + /* Intel little endian, 64-bit mantissa followed by 16-bit + sign+exponent and then either 16 or 48 bits of gap. */ + ex = adjust_address (temp, iemode, 8); + hi = adjust_address (temp, imode, 4); + lo = adjust_address (temp, imode, 0); + } + else + { + /* Big endian Itanium. */ + ex = adjust_address (temp, iemode, 0); + hi = adjust_address (temp, imode, 2); + lo = adjust_address (temp, imode, 6); + } + rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30); + gcc_assert (fmt->qnan_msb_set); + rtx mask = GEN_INT (0x7fff); + rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30); + /* For Intel/Motorola extended format, expand to: + (ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val. */ + rtx nlo = expand_unop (imode, neg_optab, lo, NULL_RTX, 0); + lo = expand_binop (imode, ior_optab, lo, nlo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + lo = expand_shift (RSHIFT_EXPR, imode, lo, 31, NULL_RTX, 1); + temp = expand_binop (imode, xor_optab, hi, bit, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (imode, ior_optab, temp, lo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (target, GTU, temp, val, imode, 1, 1); + ex = expand_binop (iemode, and_optab, ex, mask, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + ex = emit_store_flag_force (gen_reg_rtx (GET_MODE (temp)), EQ, + ex, mask, iemode, 1, 1); + temp = expand_binop (GET_MODE (temp), and_optab, temp, ex, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + } + break; + default: + gcc_unreachable (); + } + + return temp; +} + /* Expand a call to one of the builtin rounding functions gcc defines as an extension (lfloor and lceil). As these are gcc extensions we do not need to worry about setting errno to EDOM. @@ -5508,9 +5803,9 @@ expand_builtin_signbit (tree exp, rtx target) if (icode != CODE_FOR_nothing) { rtx_insn *last = get_last_insn (); - target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); - if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN)) - return target; + rtx this_target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); + if (maybe_emit_unop_insn (icode, this_target, temp, UNKNOWN)) + return this_target; delete_insns_since (last); } @@ -7120,6 +7415,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, return target; break; + case BUILT_IN_ISSIGNALING: + target = expand_builtin_issignaling (exp, target); + if (target) + return target; + break; + CASE_FLT_FN (BUILT_IN_ICEIL): CASE_FLT_FN (BUILT_IN_LCEIL): CASE_FLT_FN (BUILT_IN_LLCEIL): @@ -8395,8 +8696,6 @@ fold_builtin_strlen (location_t loc, tree expr, tree type, tree arg) static tree fold_builtin_inf (location_t loc, tree type, int warn) { - REAL_VALUE_TYPE real; - /* __builtin_inff is intended to be usable to define INFINITY on all targets. If an infinity is not available, INFINITY expands "to a positive constant of type float that overflows at translation @@ -8407,8 +8706,7 @@ fold_builtin_inf (location_t loc, tree type, int warn) if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn) pedwarn (loc, 0, "target format does not support infinity"); - real_inf (&real); - return build_real (type, real); + return build_real (type, dconstinf); } /* Fold function call to builtin sincos, sincosf, or sincosl. Return @@ -8963,6 +9261,17 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index) arg = builtin_save_expr (arg); return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg); + case BUILT_IN_ISSIGNALING: + /* Folding to true for REAL_CST is done in fold_const_call_ss. + Don't use tree_expr_signaling_nan_p (arg) -> integer_one_node + and !tree_expr_maybe_signaling_nan_p (arg) -> integer_zero_node + here, so there is some possibility of __builtin_issignaling working + without -fsignaling-nans. Especially when -fno-signaling-nans is + the default. */ + if (!tree_expr_maybe_nan_p (arg)) + return omit_one_operand_loc (loc, type, integer_zero_node, arg); + return NULL_TREE; + default: gcc_unreachable (); } @@ -9024,9 +9333,8 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs) if (tree_expr_maybe_infinite_p (arg)) { - real_inf (&r); tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg, - build_real (type, r)); + build_real (type, dconstinf)); res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_infinite, res); } @@ -9399,6 +9707,9 @@ fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0) case BUILT_IN_ISNAND128: return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISNAN); + case BUILT_IN_ISSIGNALING: + return fold_builtin_classify (loc, fndecl, arg0, BUILT_IN_ISSIGNALING); + case BUILT_IN_FREE: if (integer_zerop (arg0)) return build_empty_stmt (loc); diff --git a/gcc/builtins.def b/gcc/builtins.def index 005976f..f023631 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -908,6 +908,7 @@ DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOT DEF_GCC_BUILTIN (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_GCC_BUILTIN (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_GCC_BUILTIN (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) +DEF_GCC_BUILTIN (BUILT_IN_ISSIGNALING, "issignaling", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF) DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index c738e57..3fcf73b 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,75 @@ +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_DOACROSS. + * c-omp.cc (c_finish_omp_depobj): Check also for OMP_CLAUSE_DOACROSS + clause and diagnose it. Don't handle OMP_CLAUSE_DEPEND_SOURCE and + OMP_CLAUSE_DEPEND_SINK. Assert kind is not OMP_CLAUSE_DEPEND_INVALID. + +2022-09-02 David Malcolm <dmalcolm@redhat.com> + + PR c/90885 + * c-common.h (check_for_xor_used_as_pow): New decl. + * c-lex.cc (c_lex_with_flags): Add DECIMAL_INT to flags as appropriate. + * c-warn.cc (check_for_xor_used_as_pow): New. + * c.opt (Wxor-used-as-pow): New. + +2022-09-01 Jason Merrill <jason@redhat.com> + + * c-common.cc (c_common_nodes_and_builtins): Set TREE_STRING_FLAG on + char8_t. + (braced_list_to_string): Check for char-sized elements. + +2022-09-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/106655 + * c.opt (-Winvalid-utf8): New warning. + * c-opts.cc (c_common_handle_option) <case OPT_finput_charset_>: + Set cpp_opts->cpp_input_charset_explicit. + (c_common_post_options): If -finput-charset=UTF-8 is explicit + in C++23, enable -Winvalid-utf8 by default and if -pedantic + or -pedantic-errors, make it a pedwarn. + +2022-08-31 Joseph Myers <joseph@codesourcery.com> + + * c-attribs.cc (handle_deprecated_attribute): Check and pedwarn + for LABEL_DECL. + * c-common.cc (c_add_case_label): Add argument ATTRS. Call + decl_attributes. + * c-common.h (do_case, c_add_case_label): Update declarations. + * c-lex.cc (c_common_has_attribute): For C, produce a result of + 201910 for fallthrough and 202106 for maybe_unused. + +2022-08-26 Marek Polacek <polacek@redhat.com> + + PR c++/81159 + * c.opt (Wself-move): New option. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + * c-common.cc (check_builtin_function_arguments): Handle + BUILT_IN_ISSIGNALING. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/106648 + * c-cppbuiltin.cc (c_cpp_builtins): Predefine + __cpp_named_character_escapes to 202207L. + +2022-08-25 Marek Polacek <polacek@redhat.com> + + * c-common.cc (c_common_reswords): Enable nullptr in C2X. + (c_common_nodes_and_builtins): Create the built-in node for nullptr. + * c-common.h (enum c_tree_index): Add CTI_NULLPTR, CTI_NULLPTR_TYPE. + (struct c_common_resword): Resize the disable member. + (D_C2X): Add. + (nullptr_node): Define. + (nullptr_type_node): Define. + (NULLPTR_TYPE_P): Define. + * c-pretty-print.cc (c_pretty_printer::simple_type_specifier): Handle + NULLPTR_TYPE. + (c_pretty_printer::direct_abstract_declarator): Likewise. + (c_pretty_printer::constant): Likewise. + 2022-08-16 Tom Honermann <tom@honermann.net> PR c++/106423 diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index e4f1d35..8bb80e2 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -4163,6 +4163,13 @@ handle_deprecated_attribute (tree *node, tree name, || TREE_CODE (decl) == CONST_DECL || objc_method_decl (TREE_CODE (decl))) TREE_DEPRECATED (decl) = 1; + else if (TREE_CODE (decl) == LABEL_DECL) + { + pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", + name); + *no_add_attrs = true; + return NULL_TREE; + } else warn = 1; } diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 6e41ceb..9746504 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -324,8 +324,10 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); if they match the mask. Masks for languages: - C --std=c89: D_C99 | D_CXXONLY | D_OBJC | D_CXX_OBJC - C --std=c99: D_CXXONLY | D_OBJC + C --std=c89: D_C99 | D_C2X | D_CXXONLY | D_OBJC | D_CXX_OBJC + C --std=c99: D_C2X | D_CXXONLY | D_OBJC + C --std=c17: D_C2X | D_CXXONLY | D_OBJC + C --std=c2x: D_CXXONLY | D_OBJC ObjC is like C except that D_OBJC and D_CXX_OBJC are not set C++ --std=c++98: D_CONLY | D_CXX11 | D_CXX20 | D_OBJC C++ --std=c++11: D_CONLY | D_CXX20 | D_OBJC @@ -500,7 +502,7 @@ const struct c_common_resword c_common_reswords[] = { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, { "new", RID_NEW, D_CXXONLY | D_CXXWARN }, { "noexcept", RID_NOEXCEPT, D_CXXONLY | D_CXX11 | D_CXXWARN }, - { "nullptr", RID_NULLPTR, D_CXXONLY | D_CXX11 | D_CXXWARN }, + { "nullptr", RID_NULLPTR, D_C2X | D_CXX11 | D_CXXWARN }, { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, @@ -4548,6 +4550,7 @@ c_common_nodes_and_builtins (void) if (c_dialect_cxx ()) { char8_type_node = make_unsigned_type (char8_type_size); + TYPE_STRING_FLAG (char8_type_node) = true; if (flag_char8_t) record_builtin_type (RID_CHAR8, "char8_t", char8_type_node); @@ -4723,6 +4726,18 @@ c_common_nodes_and_builtins (void) null_node = make_int_cst (1, 1); TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0); + /* Create the built-in nullptr node. This part of its initialization is + common to C and C++. The front ends can further adjust its definition + in {c,cxx}_init_decl_processing. In particular, we aren't setting the + alignment here for C++ backward ABI bug compatibility. */ + nullptr_type_node = make_node (NULLPTR_TYPE); + TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode)); + TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode)); + TYPE_UNSIGNED (nullptr_type_node) = 1; + TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode); + SET_TYPE_MODE (nullptr_type_node, ptr_mode); + nullptr_node = build_int_cst (nullptr_type_node, 0); + /* Since builtin_types isn't gc'ed, don't export these nodes. */ memset (builtin_types, 0, sizeof (builtin_types)); } @@ -5054,11 +5069,12 @@ case_compare (splay_tree_key k1, splay_tree_key k2) CASES is a tree containing all the case ranges processed so far; COND is the condition for the switch-statement itself. Returns the CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no - CASE_LABEL_EXPR is created. */ + CASE_LABEL_EXPR is created. ATTRS are the attributes to be applied + to the label. */ tree c_add_case_label (location_t loc, splay_tree cases, tree cond, - tree low_value, tree high_value) + tree low_value, tree high_value, tree attrs) { tree type; tree label; @@ -5067,6 +5083,7 @@ c_add_case_label (location_t loc, splay_tree cases, tree cond, /* Create the LABEL_DECL itself. */ label = create_artificial_label (loc); + decl_attributes (&label, attrs, 0); /* If there was an error processing the switch condition, bail now before we get more confused. */ @@ -6294,6 +6311,7 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc, case BUILT_IN_ISINF_SIGN: case BUILT_IN_ISNAN: case BUILT_IN_ISNORMAL: + case BUILT_IN_ISSIGNALING: case BUILT_IN_SIGNBIT: if (builtin_function_validate_nargs (loc, fndecl, nargs, 1)) { @@ -9328,12 +9346,15 @@ braced_list_to_string (tree type, tree ctor, bool member) if (!member && !tree_fits_uhwi_p (typesize)) return ctor; - /* If the target char size differes from the host char size, we'd risk + /* If the target char size differs from the host char size, we'd risk loosing data and getting object sizes wrong by converting to host chars. */ if (TYPE_PRECISION (char_type_node) != CHAR_BIT) return ctor; + /* STRING_CST doesn't support wide characters. */ + gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (type)) == CHAR_BIT); + /* If the array has an explicit bound, use it to constrain the size of the string. If it doesn't, be sure to create a string that's as long as implied by the index of the last zero specified via diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index c06769b..ce971a2 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -375,6 +375,8 @@ enum c_tree_index CTI_DEFAULT_FUNCTION_TYPE, CTI_NULL, + CTI_NULLPTR, + CTI_NULLPTR_TYPE, /* These are not types, but we have to look them up all the time. */ CTI_FUNCTION_NAME_DECL, @@ -409,7 +411,7 @@ struct c_common_resword { const char *const word; ENUM_BITFIELD(rid) const rid : 16; - const unsigned int disable : 16; + const unsigned int disable : 32; }; /* Mode used to build pointers (VOIDmode means ptr_mode). */ @@ -447,19 +449,20 @@ extern machine_mode c_default_pointer_mode; #define D_CONLY 0x0001 /* C only (not in C++). */ #define D_CXXONLY 0x0002 /* C++ only (not in C). */ #define D_C99 0x0004 /* In C, C99 only. */ -#define D_CXX11 0x0008 /* In C++, C++11 only. */ -#define D_EXT 0x0010 /* GCC extension. */ -#define D_EXT89 0x0020 /* GCC extension incorporated in C99. */ -#define D_ASM 0x0040 /* Disabled by -fno-asm. */ -#define D_OBJC 0x0080 /* In Objective C and neither C nor C++. */ -#define D_CXX_OBJC 0x0100 /* In Objective C, and C++, but not C. */ -#define D_CXXWARN 0x0200 /* In C warn with -Wcxx-compat. */ -#define D_CXX_CONCEPTS 0x0400 /* In C++, only with concepts. */ -#define D_TRANSMEM 0X0800 /* C++ transactional memory TS. */ -#define D_CXX_CHAR8_T 0X1000 /* In C++, only with -fchar8_t. */ -#define D_CXX20 0x2000 /* In C++, C++20 only. */ -#define D_CXX_COROUTINES 0x4000 /* In C++, only with coroutines. */ -#define D_CXX_MODULES 0x8000 /* In C++, only with modules. */ +#define D_C2X 0x0008 /* In C, C2X only. */ +#define D_CXX11 0x0010 /* In C++, C++11 only. */ +#define D_EXT 0x0020 /* GCC extension. */ +#define D_EXT89 0x0040 /* GCC extension incorporated in C99. */ +#define D_ASM 0x0080 /* Disabled by -fno-asm. */ +#define D_OBJC 0x0100 /* In Objective C and neither C nor C++. */ +#define D_CXX_OBJC 0x0200 /* In Objective C, and C++, but not C. */ +#define D_CXXWARN 0x0400 /* In C warn with -Wcxx-compat. */ +#define D_CXX_CONCEPTS 0x0800 /* In C++, only with concepts. */ +#define D_TRANSMEM 0x1000 /* C++ transactional memory TS. */ +#define D_CXX_CHAR8_T 0x2000 /* In C++, only with -fchar8_t. */ +#define D_CXX20 0x4000 /* In C++, C++20 only. */ +#define D_CXX_COROUTINES 0x8000 /* In C++, only with coroutines. */ +#define D_CXX_MODULES 0x10000 /* In C++, only with modules. */ #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T @@ -534,6 +537,9 @@ extern const unsigned int num_c_common_reswords; /* The node for C++ `__null'. */ #define null_node c_global_trees[CTI_NULL] +/* The nodes for `nullptr'. */ +#define nullptr_node c_global_trees[CTI_NULLPTR] +#define nullptr_type_node c_global_trees[CTI_NULLPTR_TYPE] extern GTY(()) tree c_global_trees[CTI_MAX]; @@ -1009,7 +1015,10 @@ extern void c_parse_final_cleanups (void); #define DECL_UNNAMED_BIT_FIELD(NODE) \ (DECL_C_BIT_FIELD (NODE) && !DECL_NAME (NODE)) -extern tree do_case (location_t, tree, tree); +/* True iff TYPE is cv decltype(nullptr). */ +#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE) + +extern tree do_case (location_t, tree, tree, tree); extern tree build_stmt (location_t, enum tree_code, ...); extern tree build_real_imag_expr (location_t, enum tree_code, tree); @@ -1037,7 +1046,8 @@ extern tree boolean_increment (enum tree_code, tree); extern int case_compare (splay_tree_key, splay_tree_key); -extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree); +extern tree c_add_case_label (location_t, splay_tree, tree, tree, tree, + tree = NULL_TREE); extern bool c_switch_covers_all_cases_p (splay_tree, tree); extern bool c_block_may_fallthru (const_tree); @@ -1475,6 +1485,10 @@ extern tree do_warn_duplicated_branches_r (tree *, int *, void *); extern void warn_for_multistatement_macros (location_t, location_t, location_t, enum rid); +extern void check_for_xor_used_as_pow (location_t lhs_loc, tree lhs_val, + location_t operator_loc, + tree rhs_val); + /* In c-attribs.cc. */ extern bool attribute_takes_identifier_p (const_tree); extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *); diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 4672ae8..a1557eb 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1080,6 +1080,7 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__cpp_if_consteval=202106L"); cpp_define (pfile, "__cpp_constexpr=202110L"); cpp_define (pfile, "__cpp_multidimensional_subscript=202110L"); + cpp_define (pfile, "__cpp_named_character_escapes=202207L"); } if (flag_concepts) { diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc index 0b6f94e..110d029 100644 --- a/gcc/c-family/c-lex.cc +++ b/gcc/c-family/c-lex.cc @@ -381,12 +381,14 @@ c_common_has_attribute (cpp_reader *pfile, bool std_syntax) } else { - if (is_attribute_p ("deprecated", attr_name) - || is_attribute_p ("maybe_unused", attr_name) - || is_attribute_p ("fallthrough", attr_name)) + if (is_attribute_p ("deprecated", attr_name)) result = 201904; + else if (is_attribute_p ("fallthrough", attr_name)) + result = 201910; else if (is_attribute_p ("nodiscard", attr_name)) result = 202003; + else if (is_attribute_p ("maybe_unused", attr_name)) + result = 202106; } if (result) attr_name = NULL_TREE; @@ -509,7 +511,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags, /* C++ uses '0' to mark virtual functions as pure. Set PURE_ZERO to pass this information to the C++ parser. */ if (tok->val.str.len == 1 && *tok->val.str.text == '0') - add_flags = PURE_ZERO; + add_flags = PURE_ZERO | DECIMAL_INT; + else if ((flags & CPP_N_INTEGER) && (flags & CPP_N_DECIMAL)) + /* -Wxor-used-as-pow is only active for LHS of ^ expressed + as a decimal integer. */ + add_flags = DECIMAL_INT; *value = interpret_integer (tok, flags, &overflow); break; diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index 66d17a2..56bc4b1 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -714,8 +714,17 @@ c_finish_omp_depobj (location_t loc, tree depobj, if (clause) { - gcc_assert (TREE_CODE (clause) == OMP_CLAUSE - && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND); + gcc_assert (TREE_CODE (clause) == OMP_CLAUSE); + if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "%<depend(%s)%> is only allowed in %<omp ordered%>", + OMP_CLAUSE_DOACROSS_KIND (clause) + == OMP_CLAUSE_DOACROSS_SOURCE + ? "source" : "sink"); + return; + } + gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND); if (OMP_CLAUSE_CHAIN (clause)) error_at (OMP_CLAUSE_LOCATION (clause), "more than one locator in %<depend%> clause on %<depobj%> " @@ -727,13 +736,6 @@ c_finish_omp_depobj (location_t loc, tree depobj, "%<depobj%> dependence type specified in %<depend%> " "clause on %<depobj%> construct"); return; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - error_at (OMP_CLAUSE_LOCATION (clause), - "%<depend(%s)%> is only allowed in %<omp ordered%>", - OMP_CLAUSE_DEPEND_KIND (clause) == OMP_CLAUSE_DEPEND_SOURCE - ? "source" : "sink"); - return; case OMP_CLAUSE_DEPEND_IN: case OMP_CLAUSE_DEPEND_OUT: case OMP_CLAUSE_DEPEND_INOUT: @@ -765,7 +767,7 @@ c_finish_omp_depobj (location_t loc, tree depobj, } } else - gcc_assert (kind != OMP_CLAUSE_DEPEND_SOURCE); + gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID); if (depobj == error_mark_node) return; diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index 337a524..babaa2f 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -534,6 +534,7 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, case OPT_finput_charset_: cpp_opts->input_charset = arg; + cpp_opts->cpp_input_charset_explicit = 1; break; case OPT_ftemplate_depth_: @@ -1152,6 +1153,17 @@ c_common_post_options (const char **pfilename) lang_hooks.preprocess_options (parse_in); cpp_post_options (parse_in); init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in)); + /* For C++23 and explicit -finput-charset=UTF-8, turn on -Winvalid-utf8 + by default and make it a pedwarn unless -Wno-invalid-utf8. */ + if (cxx_dialect >= cxx23 + && cpp_opts->cpp_input_charset_explicit + && strcmp (cpp_opts->input_charset, "UTF-8") == 0 + && (cpp_opts->cpp_warn_invalid_utf8 + || !global_options_set.x_warn_invalid_utf8)) + { + global_options.x_warn_invalid_utf8 = 1; + cpp_opts->cpp_warn_invalid_utf8 = cpp_opts->cpp_pedantic ? 2 : 1; + } /* Let diagnostics infrastructure know how to convert input files the same way libcpp will do it, namely using the configured input charset and diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index de806a6..c894a25 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -108,6 +108,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, + PRAGMA_OMP_CLAUSE_DOACROSS, PRAGMA_OMP_CLAUSE_ENTER, PRAGMA_OMP_CLAUSE_FILTER, PRAGMA_OMP_CLAUSE_FINAL, diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc index 71a0cb5..efa1768 100644 --- a/gcc/c-family/c-pretty-print.cc +++ b/gcc/c-family/c-pretty-print.cc @@ -321,6 +321,7 @@ pp_c_pointer (c_pretty_printer *pp, tree t) _Bool -- C99 _Complex -- C99 _Imaginary -- C99 + nullptr_t -- C23 struct-or-union-specifier enum-specifier typedef-name. @@ -424,6 +425,9 @@ c_pretty_printer::simple_type_specifier (tree t) else translate_string ("<anonymous>"); break; + case NULLPTR_TYPE: + pp_c_ws_string (this, "nullptr_t"); + break; default: pp_unsupported_tree (this, t); @@ -678,6 +682,7 @@ c_pretty_printer::direct_abstract_declarator (tree t) case COMPLEX_TYPE: case TYPE_DECL: case ERROR_MARK: + case NULLPTR_TYPE: break; default: @@ -1219,6 +1224,8 @@ c_pretty_printer::constant (tree e) pp_c_character_constant (this, e); else if (TREE_CODE (type) == ENUMERAL_TYPE) pp_c_enumeration_constant (this, e); + else if (NULLPTR_TYPE_P (type)) + pp_string (this, "nullptr"); else pp_c_integer_constant (this, e); } diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index ea7335f..ed79cc3 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -3799,3 +3799,97 @@ do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1) op0, op_symbol_code (code), op1); } } + +/* Given LHS_VAL ^ RHS_VAL, where LHS_LOC is the location of the LHS and + OPERATOR_LOC is the location of the ^, complain with -Wxor-used-as-pow + if it looks like the user meant exponentiation rather than xor. */ + +void +check_for_xor_used_as_pow (location_t lhs_loc, tree lhs_val, + location_t operator_loc, + tree rhs_val) +{ + /* Only complain if both args are non-negative integer constants. */ + if (!(TREE_CODE (lhs_val) == INTEGER_CST + && tree_int_cst_sgn (lhs_val) >= 0)) + return; + if (!(TREE_CODE (rhs_val) == INTEGER_CST + && tree_int_cst_sgn (rhs_val) >= 0)) + return; + + /* Only complain if the LHS is 2 or 10. */ + unsigned HOST_WIDE_INT lhs_uhwi = tree_to_uhwi (lhs_val); + if (lhs_uhwi != 2 && lhs_uhwi != 10) + return; + + unsigned HOST_WIDE_INT rhs_uhwi = tree_to_uhwi (rhs_val); + unsigned HOST_WIDE_INT xor_result = lhs_uhwi ^ rhs_uhwi; + binary_op_rich_location loc (operator_loc, + lhs_val, rhs_val, false); + + /* If we issue fix-it hints with the warning then we will also issue a + note suggesting how to suppress the warning with a different change. + These proposed changes are incompatible. */ + loc.fixits_cannot_be_auto_applied (); + + auto_diagnostic_group d; + bool warned = false; + if (lhs_uhwi == 2) + { + /* Would exponentiation fit in int, in long long, or not at all? */ + if (rhs_uhwi < (INT_TYPE_SIZE - 1)) + { + unsigned HOST_WIDE_INT suggested_result = 1 << rhs_uhwi; + loc.add_fixit_replace (lhs_loc, "1"); + loc.add_fixit_replace (operator_loc, "<<"); + warned = warning_at (&loc, OPT_Wxor_used_as_pow, + "result of %<%wu^%wu%> is %wu;" + " did you mean %<1 << %wu%> (%wu)?", + lhs_uhwi, rhs_uhwi, xor_result, + rhs_uhwi, suggested_result); + } + else if (rhs_uhwi < (LONG_LONG_TYPE_SIZE - 1)) + { + loc.add_fixit_replace (lhs_loc, "1LL"); + loc.add_fixit_replace (operator_loc, "<<"); + warned = warning_at (&loc, OPT_Wxor_used_as_pow, + "result of %<%wu^%wu%> is %wu;" + " did you mean %<1LL << %wu%>?", + lhs_uhwi, rhs_uhwi, xor_result, + rhs_uhwi); + } + else if (rhs_uhwi <= LONG_LONG_TYPE_SIZE) + warned = warning_at (&loc, OPT_Wxor_used_as_pow, + "result of %<%wu^%wu%> is %wu;" + " did you mean exponentiation?", + lhs_uhwi, rhs_uhwi, xor_result); + /* Otherwise assume it's an xor. */ + } + else + { + gcc_assert (lhs_uhwi == 10); + loc.add_fixit_replace (lhs_loc, "1"); + loc.add_fixit_replace (operator_loc, "e"); + warned = warning_at (&loc, OPT_Wxor_used_as_pow, + "result of %<%wu^%wu%> is %wu;" + " did you mean %<1e%wu%>?", + lhs_uhwi, rhs_uhwi, xor_result, + rhs_uhwi); + } + if (warned) + { + gcc_rich_location note_loc (lhs_loc); + if (lhs_uhwi == 2) + note_loc.add_fixit_replace (lhs_loc, "0x2"); + else + { + gcc_assert (lhs_uhwi == 10); + note_loc.add_fixit_replace (lhs_loc, "0xa"); + } + note_loc.fixits_cannot_be_auto_applied (); + inform (¬e_loc, + "you can silence this warning by using a hexadecimal constant" + " (%wx rather than %wd)", + lhs_uhwi, lhs_uhwi); + } +} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index dfdebd5..4515664 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -821,6 +821,10 @@ Winvalid-pch C ObjC C++ ObjC++ CPP(warn_invalid_pch) CppReason(CPP_W_INVALID_PCH) Var(cpp_warn_invalid_pch) Init(0) Warning Warn about PCH files that are found but not used. +Winvalid-utf8 +C objC C++ ObjC++ CPP(cpp_warn_invalid_utf8) CppReason(CPP_W_INVALID_UTF8) Var(warn_invalid_utf8) Init(0) Warning +Warn about invalid UTF-8 characters in comments. + Wjump-misses-init C ObjC Var(warn_jump_misses_init) Warning LangEnabledby(C ObjC,Wc++-compat) Warn when a jump misses a variable initialization. @@ -1229,6 +1233,10 @@ Wselector ObjC ObjC++ Var(warn_selector) Warning Warn if a selector has multiple methods. +Wself-move +C++ ObjC++ Var(warn_self_move) Warning LangEnabledBy(C++ ObjC++, Wall) +Warn when a value is moved to itself with std::move. + Wsequence-point C ObjC C++ ObjC++ Var(warn_sequence_point) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about possible violations of sequence point rules. @@ -1439,6 +1447,10 @@ Wwrite-strings C ObjC C++ ObjC++ Var(warn_write_strings) Warning In C++, nonzero means warn about deprecated conversion from string literals to 'char *'. In C, similar warning, except that the conversion is of course not deprecated by the ISO C standard. +Wxor-used-as-pow +C ObjC C++ ObjC++ Var(warn_xor_used_as_pow) Warning Init(1) +Warn about xor operators where it appears the user meant exponentiation. + Wzero-as-null-pointer-constant C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning Warn when a literal '0' is used as null pointer. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index a57d62f..a97faa6 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,98 @@ +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * c-parser.cc (c_parser_omp_clause_name): Handle doacross. + (c_parser_omp_clause_depend_sink): Renamed to ... + (c_parser_omp_clause_doacross_sink): ... this. Add depend_p argument. + Handle parsing of doacross(sink:omp_cur_iteration-1). Use + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of + OMP_CLAUSE_DEPEND_SINK_NEGATIVE, build OMP_CLAUSE_DOACROSS instead + of OMP_CLAUSE_DEPEND and set OMP_CLAUSE_DOACROSS_DEPEND flag on it. + (c_parser_omp_clause_depend): Use OMP_CLAUSE_DOACROSS_SINK and + OMP_CLAUSE_DOACROSS_SOURCE instead of OMP_CLAUSE_DEPEND_SINK and + OMP_CLAUSE_DEPEND_SOURCE, build OMP_CLAUSE_DOACROSS for depend(source) + and set OMP_CLAUSE_DOACROSS_DEPEND on it. + (c_parser_omp_clause_doacross): New function. + (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_DOACROSS. + (c_parser_omp_depobj): Use OMP_CLAUSE_DEPEND_INVALID instead of + OMP_CLAUSE_DEPEND_SOURCE. + (c_parser_omp_for_loop): Don't diagnose here linear clause together + with ordered with argument. + (c_parser_omp_simd): Don't diagnose ordered clause with argument on + for simd. + (OMP_ORDERED_DEPEND_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DOACROSS. + (c_parser_omp_ordered): Handle also doacross and adjust for it + diagnostic wording. + * c-typeck.cc (c_finish_omp_clauses): Handle OMP_CLAUSE_DOACROSS. + Don't handle OMP_CLAUSE_DEPEND_SOURCE and OMP_CLAUSE_DEPEND_SINK. + +2022-09-02 David Malcolm <dmalcolm@redhat.com> + + PR c/90885 + * c-parser.cc (c_parser_string_literal): Clear ret.m_decimal. + (c_parser_expr_no_commas): Likewise. + (c_parser_conditional_expression): Likewise. + (c_parser_binary_expression): Clear m_decimal when popping the + stack. + (c_parser_unary_expression): Clear ret.m_decimal. + (c_parser_has_attribute_expression): Likewise for result. + (c_parser_predefined_identifier): Likewise for expr. + (c_parser_postfix_expression): Likewise for expr. + Set expr.m_decimal when handling a CPP_NUMBER that was a decimal + token. + * c-tree.h (c_expr::m_decimal): New bitfield. + * c-typeck.cc (parser_build_binary_op): Clear result.m_decimal. + (parser_build_binary_op): Call check_for_xor_used_as_pow. + +2022-09-01 Joseph Myers <joseph@codesourcery.com> + + * c-decl.cc (grokparms): Handle () in a function declaration the + same as (void) for C2X. + +2022-08-31 Joseph Myers <joseph@codesourcery.com> + + * c-parser.cc (c_parser_label): Pass attributes to do_case. + * c-typeck.cc (do_case): Add argument ATTRS. Pass it to + c_add_case_label. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + * c-typeck.cc (convert_arguments): Handle BUILT_IN_ISSIGNALING. + +2022-08-25 Marek Polacek <polacek@redhat.com> + + * c-convert.cc (c_convert) <case POINTER_TYPE>: Handle NULLPTR_TYPE. + Give a better diagnostic when converting to nullptr_t. + * c-decl.cc (c_init_decl_processing): Perform C-specific nullptr + initialization. + * c-parser.cc (c_parse_init): Maybe OR D_C2X into mask. + (c_parser_postfix_expression): Handle RID_NULLPTR. + * c-typeck.cc (null_pointer_constant_p): Return true when expr is + nullptr_node. + (build_unary_op) <case TRUTH_NOT_EXPR>: Handle NULLPTR_TYPE. + (build_conditional_expr): Handle the case when the second/third operand + is NULLPTR_TYPE and third/second operand is POINTER_TYPE. + (convert_for_assignment): Handle converting an expression of type + nullptr_t to pointer/bool. + (build_binary_op) <case TRUTH_XOR_EXPR>: Handle NULLPTR_TYPE. + <case EQ_EXPR>: Handle comparing operands of type nullptr_t. + +2022-08-25 Joseph Myers <joseph@codesourcery.com> + + * c-decl.cc (start_decl): Do not diagnose initialization of + variable-sized objects here. + * c-parser.cc (c_parser_braced_init): Add argument DECL. All + callers changed. + (c_parser_initializer): Diagnose initialization of variable-sized + objects other than with braced initializer. + (c_parser_braced_init): Use pedwarn_c11 for empty initializer + braces and update diagnostic text. Diagnose initialization of + variable-sized objects with nonempty braces. + * c-typeck.cc (digest_init): Update diagnostic for initialization + of variable-sized objects. + (really_start_incremental_init, set_designator) + (process_init_element): Update comments. + (pop_init_level): Allow scalar empty initializers. + 2022-08-17 Tobias Burnus <tobias@codesourcery.com> Chung-Lin Tang <cltang@codesourcery.com> diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc index 18083d5..6e74913 100644 --- a/gcc/c/c-convert.cc +++ b/gcc/c/c-convert.cc @@ -133,6 +133,20 @@ c_convert (tree type, tree expr, bool init_const) (loc, type, c_objc_common_truthvalue_conversion (input_location, expr)); case POINTER_TYPE: + /* The type nullptr_t may be converted to a pointer type. The result is + a null pointer value. */ + if (NULLPTR_TYPE_P (TREE_TYPE (e))) + { + /* To make sure that (void *)nullptr is not a null pointer constant, + build_c_cast will create an additional NOP_EXPR around the result + of this conversion. */ + if (TREE_SIDE_EFFECTS (e)) + ret = build2 (COMPOUND_EXPR, type, e, build_int_cst (type, 0)); + else + ret = build_int_cst (type, 0); + goto maybe_fold; + } + gcc_fallthrough (); case REFERENCE_TYPE: ret = convert_to_pointer (type, e); goto maybe_fold; @@ -180,7 +194,16 @@ c_convert (tree type, tree expr, bool init_const) return ret; } - error ("conversion to non-scalar type requested"); + /* If we are converting to nullptr_t, don't say "non-scalar type" because + the nullptr_t type is a scalar type. Only nullptr_t shall be converted + to nullptr_t. */ + if (code == NULLPTR_TYPE) + { + error ("conversion from %qT to %qT", TREE_TYPE (e), type); + inform (input_location, "only %qT can be converted to %qT", type, type); + } + else + error ("conversion to non-scalar type requested"); return error_mark_node; } diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 9e590c6..34f8fed 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -4531,6 +4531,12 @@ c_init_decl_processing (void) pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier ("_Bool"), boolean_type_node)); + /* C-specific nullptr initialization. */ + record_builtin_type (RID_MAX, "nullptr_t", nullptr_type_node); + /* The size and alignment of nullptr_t is the same as for a pointer to + character type. */ + SET_TYPE_ALIGN (nullptr_type_node, GET_MODE_ALIGNMENT (ptr_mode)); + input_location = save_loc; make_fname_decl = c_make_fname_decl; @@ -5180,29 +5186,15 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, initialized = false; else if (COMPLETE_TYPE_P (TREE_TYPE (decl))) { - /* A complete type is ok if size is fixed. */ - - if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl))) - || C_DECL_VARIABLE_SIZE (decl)) - { - error ("variable-sized object may not be initialized"); - initialized = false; - } + /* A complete type is ok if size is fixed. If the size is + variable, an empty initializer is OK and nonempty + initializers will be diagnosed in the parser. */ } else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) { error ("variable %qD has initializer but incomplete type", decl); initialized = false; } - else if (C_DECL_VARIABLE_SIZE (decl)) - { - /* Although C99 is unclear about whether incomplete arrays - of VLAs themselves count as VLAs, it does not make - sense to permit them to be initialized given that - ordinary VLAs may not be initialized. */ - error ("variable-sized object may not be initialized"); - initialized = false; - } } if (initialized) @@ -7876,7 +7868,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) error ("%<[*]%> not allowed in other than function prototype scope"); } - if (arg_types == NULL_TREE && !funcdef_flag + if (arg_types == NULL_TREE && !funcdef_flag && !flag_isoc2x && !in_system_header_at (input_location)) warning (OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -7904,9 +7896,8 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) tree parm, type, typelt; unsigned int parmno; - /* In C2X, convert () in a function definition to (void). */ + /* In C2X, convert () to (void). */ if (flag_isoc2x - && funcdef_flag && !arg_types && !arg_info->parms) arg_types = arg_info->types = void_list_node; diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 759f200..65d73a6 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -119,6 +119,8 @@ c_parse_init (void) mask |= D_CXXONLY; if (!flag_isoc99) mask |= D_C99; + if (!flag_isoc2x) + mask |= D_C2X; if (flag_no_asm) { mask |= D_ASM | D_EXT; @@ -1523,7 +1525,7 @@ static tree c_parser_simple_asm_expr (c_parser *); static tree c_parser_gnu_attributes (c_parser *); static struct c_expr c_parser_initializer (c_parser *, tree); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, - struct obstack *); + struct obstack *, tree); static void c_parser_initelt (c_parser *, struct obstack *); static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *); @@ -5220,11 +5222,15 @@ static struct c_expr c_parser_initializer (c_parser *parser, tree decl) { if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - return c_parser_braced_init (parser, NULL_TREE, false, NULL); + return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl); else { struct c_expr ret; location_t loc = c_parser_peek_token (parser)->location; + if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) + error_at (loc, + "variable-sized object may not be initialized except " + "with an empty initializer"); ret = c_parser_expr_no_commas (parser, NULL); /* This is handled mostly by gimplify.cc, but we have to deal with not warning about int x = x; as it is a GCC extension to turn off @@ -5251,11 +5257,12 @@ location_t last_init_list_comma; compound literal, and NULL_TREE for other initializers and for nested braced lists. NESTED_P is true for nested braced lists, false for the list of a compound literal or the list that is the - top-level initializer in a declaration. */ + top-level initializer in a declaration. DECL is the declaration for + the top-level initializer for a declaration, otherwise NULL_TREE. */ static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p, - struct obstack *outer_obstack) + struct obstack *outer_obstack, tree decl) { struct c_expr ret; struct obstack braced_init_obstack; @@ -5273,10 +5280,15 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, really_start_incremental_init (type); if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { - pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces"); + pedwarn_c11 (brace_loc, OPT_Wpedantic, + "ISO C forbids empty initializer braces before C2X"); } else { + if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) + error_at (brace_loc, + "variable-sized object may not be initialized except " + "with an empty initializer"); /* Parse a non-empty initializer list, possibly with a trailing comma. */ while (true) @@ -5532,7 +5544,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) init = c_parser_braced_init (parser, NULL_TREE, true, - braced_init_obstack); + braced_init_obstack, NULL_TREE); else { init = c_parser_expr_no_commas (parser, after); @@ -5900,14 +5912,14 @@ c_parser_label (c_parser *parser, tree std_attrs) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - label = do_case (loc1, exp1, NULL_TREE); + label = do_case (loc1, exp1, NULL_TREE, std_attrs); } else if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) { c_parser_consume_token (parser); exp2 = c_parser_expr_no_commas (parser, NULL).value; if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) - label = do_case (loc1, exp1, exp2); + label = do_case (loc1, exp1, exp2, std_attrs); } else c_parser_error (parser, "expected %<:%> or %<...%>"); @@ -5916,7 +5928,7 @@ c_parser_label (c_parser *parser, tree std_attrs) { c_parser_consume_token (parser); if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) - label = do_case (loc1, NULL_TREE, NULL_TREE); + label = do_case (loc1, NULL_TREE, NULL_TREE, std_attrs); } else { @@ -7519,6 +7531,7 @@ c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok) ret.original_code = STRING_CST; ret.original_type = NULL_TREE; set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc)); + ret.m_decimal = 0; parser->seen_string_literal = true; return ret; } @@ -7598,6 +7611,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after, ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type, code, exp_location, rhs.value, rhs.original_type); + ret.m_decimal = 0; set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ()); if (code == NOP_EXPR) ret.original_code = MODIFY_EXPR; @@ -7735,6 +7749,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after, : NULL); } set_c_expr_source_range (&ret, start, exp2.get_finish ()); + ret.m_decimal = 0; return ret; } @@ -7924,6 +7939,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, TREE_OPERAND (t, 0) = stack[0].expr.value; \ TREE_OPERAND (t, 1) = stack[1].expr.value; \ stack[0].expr.value = t; \ + stack[0].expr.m_decimal = 0; \ } \ else \ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ @@ -8210,6 +8226,7 @@ c_parser_unary_expression (c_parser *parser) ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR); ret.src_range.m_start = op_loc; ret.src_range.m_finish = finish; + ret.m_decimal = 0; return ret; } case CPP_PLUS: @@ -8583,6 +8600,7 @@ c_parser_has_attribute_expression (c_parser *parser) result.value = boolean_false_node; set_c_expr_source_range (&result, start, finish); + result.m_decimal = 0; return result; } @@ -8948,6 +8966,7 @@ c_parser_predefined_identifier (c_parser *parser) expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword, c_parser_peek_token (parser)->value); set_c_expr_source_range (&expr, loc, loc); + expr.m_decimal = 0; c_parser_consume_token (parser); return expr; } @@ -9026,12 +9045,14 @@ c_parser_postfix_expression (c_parser *parser) source_range tok_range = c_parser_peek_token (parser)->get_range (); expr.original_code = ERROR_MARK; expr.original_type = NULL; + expr.m_decimal = 0; switch (c_parser_peek_token (parser)->type) { case CPP_NUMBER: expr.value = c_parser_peek_token (parser)->value; set_c_expr_source_range (&expr, tok_range); loc = c_parser_peek_token (parser)->location; + expr.m_decimal = c_parser_peek_token (parser)->flags & DECIMAL_INT; c_parser_consume_token (parser); if (TREE_CODE (expr.value) == FIXED_CST && !targetm.fixed_point_supported_p ()) @@ -10243,6 +10264,14 @@ c_parser_postfix_expression (c_parser *parser) "%<depend%> clause"); expr.set_error (); break; + /* C23 'nullptr' literal. */ + case RID_NULLPTR: + c_parser_consume_token (parser); + expr.value = nullptr_node; + set_c_expr_source_range (&expr, tok_range); + pedwarn_c11 (loc, OPT_Wpedantic, + "ISO C does not support %qs before C2X", "nullptr"); + break; default: c_parser_error (parser, "expected expression"); expr.set_error (); @@ -10307,7 +10336,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, error_at (type_loc, "compound literal has variable size"); type = error_mark_node; } - init = c_parser_braced_init (parser, type, false, NULL); + init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE); finish_init (); maybe_warn_string_init (type_loc, type, init); @@ -12794,6 +12823,8 @@ c_parser_omp_clause_name (c_parser *parser) result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; else if (!strcmp ("dist_schedule", p)) result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; + else if (!strcmp ("doacross", p)) + result = PRAGMA_OMP_CLAUSE_DOACROSS; break; case 'e': if (!strcmp ("enter", p)) @@ -15942,8 +15973,8 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list) */ static tree -c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, - tree list) +c_parser_omp_clause_doacross_sink (c_parser *parser, location_t clause_loc, + tree list, bool depend_p) { tree vec = NULL; if (c_parser_next_token_is_not (parser, CPP_NAME) @@ -15953,6 +15984,31 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, return list; } + if (!depend_p) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "omp_cur_iteration") == 0 + && c_parser_peek_2nd_token (parser)->type == CPP_MINUS + && c_parser_peek_nth_token (parser, 3)->type == CPP_NUMBER + && c_parser_peek_nth_token (parser, 4)->type == CPP_CLOSE_PAREN) + { + tree val = c_parser_peek_nth_token (parser, 3)->value; + if (integer_onep (val) + && comptypes (TREE_TYPE (val), integer_type_node)) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + c_parser_consume_token (parser); + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_CHAIN (u) = list; + return u; + } + } + } + + + while (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_ID) { @@ -15998,7 +16054,7 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, { vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (c_parser_next_token_is_not (parser, CPP_COMMA) @@ -16012,8 +16068,9 @@ c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc, if (vec == NULL_TREE) return list; - tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; OMP_CLAUSE_DECL (u) = nreverse (vec); OMP_CLAUSE_CHAIN (u) = list; return u; @@ -16205,6 +16262,7 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; + enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; tree nl, c, iterators = NULL_TREE; matching_parens parens; @@ -16236,9 +16294,9 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) else if (strcmp ("depobj", p) == 0) kind = OMP_CLAUSE_DEPEND_DEPOBJ; else if (strcmp ("sink", p) == 0) - kind = OMP_CLAUSE_DEPEND_SINK; + dkind = OMP_CLAUSE_DOACROSS_SINK; else if (strcmp ("source", p) == 0) - kind = OMP_CLAUSE_DEPEND_SOURCE; + dkind = OMP_CLAUSE_DOACROSS_SOURCE; else goto invalid_kind; break; @@ -16248,18 +16306,20 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) c_parser_consume_token (parser); if (iterators - && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK)) + && (dkind == OMP_CLAUSE_DOACROSS_SOURCE + || dkind == OMP_CLAUSE_DOACROSS_SINK)) { pop_scope (); error_at (clause_loc, "%<iterator%> modifier incompatible with %qs", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); iterators = NULL_TREE; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) { - c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = kind; + c = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = dkind; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; parens.skip_until_found_close (parser); @@ -16269,8 +16329,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) goto resync_fail; - if (kind == OMP_CLAUSE_DEPEND_SINK) - nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list); + if (dkind == OMP_CLAUSE_DOACROSS_SINK) + nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, true); else { nl = c_parser_omp_variable_list (parser, clause_loc, @@ -16306,6 +16366,65 @@ c_parser_omp_clause_depend (c_parser *parser, tree list) return list; } +/* OpenMP 5.2: + doacross ( source : ) + doacross ( source : omp_cur_iteration ) + + doacross ( sink : vec ) + doacross ( sink : omp_cur_iteration - logical_iteration ) */ + +static tree +c_parser_omp_clause_doacross (c_parser *parser, tree list) +{ + location_t clause_loc = c_parser_peek_token (parser)->location; + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; + tree nl; + const char *p; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (c_parser_next_token_is_not (parser, CPP_NAME)) + goto invalid_kind; + + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp ("sink", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SINK; + else if (strcmp ("source", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SOURCE; + else + goto invalid_kind; + + c_parser_consume_token (parser); + + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + goto resync_fail; + + if (kind == OMP_CLAUSE_DOACROSS_SOURCE) + { + if (c_parser_next_token_is (parser, CPP_NAME) + && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), + "omp_cur_iteration") == 0) + c_parser_consume_token (parser); + nl = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (nl) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DECL (nl) = NULL_TREE; + OMP_CLAUSE_CHAIN (nl) = list; + } + else + nl = c_parser_omp_clause_doacross_sink (parser, clause_loc, list, false); + + parens.skip_until_found_close (parser); + return nl; + + invalid_kind: + c_parser_error (parser, "invalid doacross kind"); + resync_fail: + parens.skip_until_found_close (parser); + return list; +} + /* OpenMP 4.0: map ( map-kind: variable-list ) map ( variable-list ) @@ -17223,6 +17342,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, clauses = c_parser_omp_clause_depend (parser, clauses); c_name = "depend"; break; + case PRAGMA_OMP_CLAUSE_DOACROSS: + clauses = c_parser_omp_clause_doacross (parser, clauses); + c_name = "doacross"; + break; case PRAGMA_OMP_CLAUSE_MAP: clauses = c_parser_omp_clause_map (parser, clauses); c_name = "map"; @@ -19167,7 +19290,7 @@ c_parser_omp_depobj (c_parser *parser) parens.skip_until_found_close (parser); tree clause = NULL_TREE; - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; location_t c_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -19206,7 +19329,7 @@ c_parser_omp_depobj (c_parser *parser) else if (!strcmp ("inoutset", p2)) kind = OMP_CLAUSE_DEPEND_INOUTSET; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " @@ -19218,7 +19341,7 @@ c_parser_omp_depobj (c_parser *parser) clause = error_mark_node; } } - if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE) + if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause"); @@ -19417,19 +19540,6 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, = build_int_cst (NULL_TREE, collapse); ordered = collapse; } - if (ordered) - { - for (tree *pc = &clauses; *pc; ) - if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) - { - error_at (OMP_CLAUSE_LOCATION (*pc), - "%<linear%> clause may not be specified together " - "with %<ordered%> clause with a parameter"); - *pc = OMP_CLAUSE_CHAIN (*pc); - } - else - pc = &OMP_CLAUSE_CHAIN (*pc); - } gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; @@ -19867,15 +19977,6 @@ c_parser_omp_simd (location_t loc, c_parser *parser, { omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; - tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR], - OMP_CLAUSE_ORDERED); - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> clause with parameter may not be specified " - "on %qs construct", p_name); - OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; - } } block = c_begin_compound_stmt (true); @@ -20114,14 +20215,18 @@ c_parser_omp_masked (location_t loc, c_parser *parser, # pragma omp ordered ordered-clauses new-line structured-block - # pragma omp ordered depend-clauses new-line */ + # pragma omp ordered depend-clauses new-line + + OpenMP 5.2 + # pragma omp ordered doacross-clauses new-line */ #define OMP_ORDERED_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ - (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) static bool c_parser_omp_ordered (c_parser *parser, enum pragma_context context, @@ -20141,7 +20246,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (!strcmp ("depend", p)) + if (!strcmp ("depend", p) || !strcmp ("doacross", p)) { if (!flag_openmp) /* flag_openmp_simd */ { @@ -20151,8 +20256,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, if (context == pragma_stmt) { error_at (loc, - "%<#pragma omp ordered%> with %<depend%> clause may " - "only be used in compound statements"); + "%<#pragma omp ordered%> with %qs clause may " + "only be used in compound statements", p); c_parser_skip_to_pragma_eol (parser, false); return true; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index e655afd..b4231a1 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -147,6 +147,9 @@ struct c_expr etc), so we stash a copy here. */ source_range src_range; + /* True if this was directly from a decimal constant token. */ + bool m_decimal : 1; + /* Access to the first and last locations within the source spelling of this expression. */ location_t get_start () const { return src_range.m_start; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index de8780a..9ada5d2 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -133,6 +133,13 @@ null_pointer_constant_p (const_tree expr) /* This should really operate on c_expr structures, but they aren't yet available everywhere required. */ tree type = TREE_TYPE (expr); + + /* An integer constant expression with the value 0, such an expression + cast to type void*, or the predefined constant nullptr, are a null + pointer constant. */ + if (expr == nullptr_node) + return true; + return (TREE_CODE (expr) == INTEGER_CST && !TREE_OVERFLOW (expr) && integer_zerop (expr) @@ -3546,6 +3553,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist, case BUILT_IN_ISINF_SIGN: case BUILT_IN_ISNAN: case BUILT_IN_ISNORMAL: + case BUILT_IN_ISSIGNALING: case BUILT_IN_FPCLASSIFY: type_generic_remove_excess_precision = true; break; @@ -3821,6 +3829,7 @@ parser_build_binary_op (location_t location, enum tree_code code, struct c_expr arg1, struct c_expr arg2) { struct c_expr result; + result.m_decimal = 0; enum tree_code code1 = arg1.original_code; enum tree_code code2 = arg2.original_code; @@ -3978,6 +3987,14 @@ parser_build_binary_op (location_t location, enum tree_code code, "comparison between %qT and %qT", type1, type2); + if (warn_xor_used_as_pow + && code == BIT_XOR_EXPR + && arg1.m_decimal + && arg2.m_decimal) + check_for_xor_used_as_pow (arg1.get_location (), arg1.value, + location, + arg2.value); + return result; } @@ -4575,7 +4592,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, case TRUTH_NOT_EXPR: if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE && typecode != REAL_TYPE && typecode != POINTER_TYPE - && typecode != COMPLEX_TYPE) + && typecode != COMPLEX_TYPE && typecode != NULLPTR_TYPE) { error_at (location, "wrong type argument to unary exclamation mark"); @@ -5515,6 +5532,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, } result_type = type2; } + /* 6.5.15: "if one is a null pointer constant (other than a pointer) or has + type nullptr_t and the other is a pointer, the result type is the pointer + type." */ + else if (code1 == NULLPTR_TYPE && code2 == POINTER_TYPE) + result_type = type2; + else if (code1 == POINTER_TYPE && code2 == NULLPTR_TYPE) + result_type = type1; if (!result_type) { @@ -7613,12 +7637,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, error_at (location, msg); return error_mark_node; } - else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) + else if (codel == POINTER_TYPE + && (coder == INTEGER_TYPE || coder == NULLPTR_TYPE)) { - /* An explicit constant 0 can convert to a pointer, - or one that results from arithmetic, even including - a cast to integer type. */ - if (!null_pointer_constant) + /* An explicit constant 0 or type nullptr_t can convert to a pointer, + or one that results from arithmetic, even including a cast to + integer type. */ + if (!null_pointer_constant && coder != NULLPTR_TYPE) switch (errtype) { case ic_argpass: @@ -7691,7 +7716,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, return convert (type, rhs); } - else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE) + else if (codel == BOOLEAN_TYPE + /* The type nullptr_t may be converted to bool. The + result is false. */ + && (coder == POINTER_TYPE || coder == NULLPTR_TYPE)) { tree ret; bool save = in_late_binary_op; @@ -8291,7 +8319,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) { - error_init (init_loc, "variable-sized object may not be initialized"); + error_init (init_loc, + "variable-sized object may not be initialized except " + "with an empty initializer"); return error_mark_node; } @@ -8641,8 +8671,9 @@ really_start_incremental_init (tree type) constructor_max_index = integer_minus_one_node; /* constructor_max_index needs to be an INTEGER_CST. Attempts - to initialize VLAs will cause a proper error; avoid tree - checking errors as well by setting a safe value. */ + to initialize VLAs with a nonempty initializer will cause a + proper error; avoid tree checking errors as well by setting a + safe value. */ if (constructor_max_index && TREE_CODE (constructor_max_index) != INTEGER_CST) constructor_max_index = integer_minus_one_node; @@ -9024,12 +9055,14 @@ pop_init_level (location_t loc, int implicit, && !gnu_vector_type_p (constructor_type)) { /* A nonincremental scalar initializer--just return - the element, after verifying there is just one. */ + the element, after verifying there is just one. + Empty scalar initializers are supported in C2X. */ if (vec_safe_is_empty (constructor_elements)) { - if (!constructor_erroneous && constructor_type != error_mark_node) - error_init (loc, "empty scalar initializer"); - ret.value = error_mark_node; + if (constructor_erroneous || constructor_type == error_mark_node) + ret.value = error_mark_node; + else + ret.value = build_zero_cst (constructor_type); } else if (vec_safe_length (constructor_elements) != 1) { @@ -9114,7 +9147,7 @@ set_designator (location_t loc, bool array, return true; /* Likewise for an initializer for a variable-size type. Those are - diagnosed in digest_init. */ + diagnosed in the parser, except for empty initializer braces. */ if (COMPLETE_TYPE_P (constructor_type) && TREE_CODE (TYPE_SIZE (constructor_type)) != INTEGER_CST) return true; @@ -10275,7 +10308,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, return; /* Ignore elements of an initializer for a variable-size type. - Those are diagnosed in digest_init. */ + Those are diagnosed in the parser (empty initializer braces are OK). */ if (COMPLETE_TYPE_P (constructor_type) && !poly_int_tree_p (TYPE_SIZE (constructor_type))) return; @@ -11148,10 +11181,10 @@ c_start_switch (location_t switch_loc, return add_stmt (cs->switch_stmt); } -/* Process a case label at location LOC. */ +/* Process a case label at location LOC, with attributes ATTRS. */ tree -do_case (location_t loc, tree low_value, tree high_value) +do_case (location_t loc, tree low_value, tree high_value, tree attrs) { tree label = NULL_TREE; @@ -11187,7 +11220,7 @@ do_case (location_t loc, tree low_value, tree high_value) label = c_add_case_label (loc, c_switch_stack->cases, SWITCH_STMT_COND (c_switch_stack->switch_stmt), - low_value, high_value); + low_value, high_value, attrs); if (label == error_mark_node) label = NULL_TREE; return label; @@ -12107,10 +12140,10 @@ build_binary_op (location_t location, enum tree_code code, case TRUTH_XOR_EXPR: if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == FIXED_POINT_TYPE) + || code0 == FIXED_POINT_TYPE || code0 == NULLPTR_TYPE) && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE - || code1 == FIXED_POINT_TYPE)) + || code1 == FIXED_POINT_TYPE || code1 == NULLPTR_TYPE)) { /* Result of these operations is always an int, but that does not mean the operands should be @@ -12418,6 +12451,27 @@ build_binary_op (location_t location, enum tree_code code, result_type = type1; pedwarn (location, 0, "comparison between pointer and integer"); } + /* 6.5.9: One of the following shall hold: + -- both operands have type nullptr_t; */ + else if (code0 == NULLPTR_TYPE && code1 == NULLPTR_TYPE) + { + result_type = nullptr_type_node; + /* No need to convert the operands to result_type later. */ + converted = 1; + } + /* -- one operand has type nullptr_t and the other is a null pointer + constant. We will have to convert the former to the type of the + latter, because during gimplification we can't have mismatching + comparison operand type. We convert from nullptr_t to the other + type, since only nullptr_t can be converted to nullptr_t. Also, + even a constant 0 is a null pointer constant, so we may have to + create a pointer type from its type. */ + else if (code0 == NULLPTR_TYPE && null_pointer_constant_p (orig_op1)) + result_type = (INTEGRAL_TYPE_P (type1) + ? build_pointer_type (type1) : type1); + else if (code1 == NULLPTR_TYPE && null_pointer_constant_p (orig_op0)) + result_type = (INTEGRAL_TYPE_P (type0) + ? build_pointer_type (type0) : type0); if ((TREE_CODE (TREE_TYPE (orig_op0)) == BOOLEAN_TYPE || truth_value_p (TREE_CODE (orig_op0))) ^ (TREE_CODE (TREE_TYPE (orig_op1)) == BOOLEAN_TYPE @@ -14789,15 +14843,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; - case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) - { - gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_SOURCE); - break; - } - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + break; + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { gcc_assert (TREE_CODE (t) == TREE_LIST); for (; t; t = TREE_CHAIN (t)) @@ -14825,7 +14875,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } break; } - /* FALLTHRU */ + gcc_unreachable (); + case OMP_CLAUSE_DEPEND: case OMP_CLAUSE_AFFINITY: t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST diff --git a/gcc/collect2.cc b/gcc/collect2.cc index d81c7f2..9715e8e 100644 --- a/gcc/collect2.cc +++ b/gcc/collect2.cc @@ -2784,13 +2784,6 @@ scan_prog_file (const char *prog_name, scanpass which_pass, if ((name = ldgetname (ldptr, &symbol)) == NULL) continue; /* Should never happen. */ -#ifdef XCOFF_DEBUGGING_INFO - /* All AIX function names have a duplicate entry - beginning with a dot. */ - if (*name == '.') - ++name; -#endif - switch (is_ctor_dtor (name)) { #if TARGET_AIX_VERSION diff --git a/gcc/common.opt b/gcc/common.opt index fba90ff..06ef768 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -122,12 +122,6 @@ uint32_t write_symbols = NO_DEBUG Variable enum debug_info_levels debug_info_level = DINFO_LEVEL_NONE -; Nonzero means use GNU-only extensions in the generated symbolic -; debugging information. Currently, this only has an effect when -; write_symbols is set to DBX_DEBUG or XCOFF_DEBUG. -Variable -bool use_gnu_debug_info_extensions - ; Level of CTF debugging information we are producing. See flag-types.h ; for the definitions of the different possible levels. Variable @@ -3323,7 +3317,7 @@ Common Driver JoinedOrMissing Negative(gdwarf-) Generate debug information in default version of DWARF format. gdwarf- -Common Driver Joined UInteger Var(dwarf_version) Init(5) Negative(gstabs) +Common Driver Joined UInteger Var(dwarf_version) Init(5) Generate debug information in DWARF v2 (or later) format. gdwarf32 @@ -3371,12 +3365,12 @@ Common Driver Var(dwarf_split_debug_info) Init(0) Generate debug information in separate .dwo files. gstabs -Common Driver JoinedOrMissing Negative(gstabs+) -Generate debug information in STABS format. +Common Driver WarnRemoved +Does nothing. Preserved for backward compatibility. gstabs+ -Common Driver JoinedOrMissing Negative(gvms) -Generate debug information in extended STABS format. +Common Driver WarnRemoved +Does nothing. Preserved for backward compatibility. gstatement-frontiers Common Driver Var(debug_nonbind_markers_p) PerFunction @@ -3402,16 +3396,16 @@ gvariable-location-views=incompat5 Common Driver RejectNegative Var(debug_variable_location_views, -1) Init(2) gvms -Common Driver JoinedOrMissing Negative(gxcoff) +Common Driver JoinedOrMissing Generate debug information in VMS format. gxcoff -Common Driver JoinedOrMissing Negative(gxcoff+) -Generate debug information in XCOFF format. +Common Driver WarnRemoved +Does nothing. Preserved for backward compatibility. gxcoff+ -Common Driver JoinedOrMissing Negative(gdwarf) -Generate debug information in extended XCOFF format. +Common Driver JoinedOrMissing WarnRemoved +Does nothing. Preserved for backward compatibility. Enum Name(compressed_debug_sections) Type(int) diff --git a/gcc/common/common-target.def b/gcc/common/common-target.def index c4d1144..c4c6230 100644 --- a/gcc/common/common-target.def +++ b/gcc/common/common-target.def @@ -84,6 +84,31 @@ The result will be pruned to cases with PREFIX if not NULL.", vec<const char *>, (int option_code, const char *prefix), default_get_valid_option_values) +DEFHOOK +(compute_multilib, + "Some targets like RISC-V might have complicated multilib reuse rules which\n\ +are hard to implement with the current multilib scheme. This hook allows\n\ +targets to override the result from the built-in multilib mechanism.\n\ +@var{switches} is the raw option list with @var{n_switches} items;\n\ +@var{multilib_dir} is the multi-lib result which is computed by the built-in\n\ +multi-lib mechanism;\n\ +@var{multilib_defaults} is the default options list for multi-lib;\n\ +@var{multilib_select} is the string containing the list of supported\n\ +multi-libs, and the option checking list.\n\ +@var{multilib_matches}, @var{multilib_exclusions}, and @var{multilib_reuse}\n\ +are corresponding to @var{MULTILIB_MATCHES}, @var{MULTILIB_EXCLUSIONS},\n\ +and @var{MULTILIB_REUSE}.\n\ +The default definition does nothing but return @var{multilib_dir} directly.", + const char *, (const struct switchstr *switches, + int n_switches, + const char *multilib_dir, + const char *multilib_defaults, + const char *multilib_select, + const char *multilib_matches, + const char *multilib_exclusions, + const char *multilib_reuse), + default_compute_multilib) + /* Leave the boolean fields at the end. */ /* True if unwinding tables should be generated by default. */ diff --git a/gcc/common/common-targhooks.cc b/gcc/common/common-targhooks.cc index 46f5c61..7499be2 100644 --- a/gcc/common/common-targhooks.cc +++ b/gcc/common/common-targhooks.cc @@ -90,3 +90,18 @@ const struct default_options empty_optimization_table[] = { { OPT_LEVELS_NONE, 0, NULL, 0 } }; + +/* Default version of TARGET_COMPUTE_MULTILIB. */ +const char * +default_compute_multilib( + const struct switchstr *, + int, + const char *multilib, + const char *, + const char *, + const char *, + const char *, + const char *) +{ + return multilib; +} diff --git a/gcc/common/common-targhooks.h b/gcc/common/common-targhooks.h index cd49c7d..1f03495 100644 --- a/gcc/common/common-targhooks.h +++ b/gcc/common/common-targhooks.h @@ -32,4 +32,15 @@ extern vec<const char *> default_get_valid_option_values (int, const char *); extern const struct default_options empty_optimization_table[]; +const char * +default_compute_multilib( + const struct switchstr *, + int, + const char *multilib, + const char *, + const char *, + const char *, + const char *, + const char *); + #endif diff --git a/gcc/common/config/cr16/cr16-common.cc b/gcc/common/config/cr16/cr16-common.cc deleted file mode 100644 index 6d0b2be..0000000 --- a/gcc/common/config/cr16/cr16-common.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* Common hooks for CR16. - Copyright (C) 2012-2022 Free Software Foundation, Inc. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "common/common-target.h" -#include "common/common-target-def.h" - -struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 4ee1b31..cb3a5d2 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ #include <sstream> +#include <vector> #define INCLUDE_STRING #include "config.h" @@ -230,6 +231,26 @@ const riscv_subset_list *riscv_current_subset_list () return current_subset_list; } +/* struct for recording multi-lib info. */ +struct riscv_multi_lib_info_t { + std::string path; + std::string arch_str; + std::string abi_str; + std::vector<std::string> conds; + riscv_subset_list *subset_list; + + static bool parse (struct riscv_multi_lib_info_t *, + const std::string &, + const std::vector<std::string> &); +}; + +/* Flag for checking if there is no suitable multi-lib found. */ +static bool riscv_no_matched_multi_lib; + +/* Used for record value of -march and -mabi. */ +static std::string riscv_current_arch_str; +static std::string riscv_current_abi_str; + riscv_subset_t::riscv_subset_t () : name (), major_version (0), minor_version (0), next (NULL), explicit_version_p (false), implied_p (false) @@ -255,6 +276,42 @@ riscv_subset_list::~riscv_subset_list () } } +/* Compute the match score of two arch string, return 0 if incompatible. */ +int +riscv_subset_list::match_score (riscv_subset_list *list) const +{ + riscv_subset_t *s; + int score = 0; + bool has_a_ext, list_has_a_ext; + + /* Impossible to match if XLEN is different. */ + if (list->m_xlen != this->m_xlen) + return 0; + + /* There is different code gen in libstdc++ and libatomic between w/ A-ext + and w/o A-ext, and it not work if using soft and hard atomic mechanism + at same time, so they are incompatible. */ + has_a_ext = this->lookup ("a") != NULL; + list_has_a_ext = list->lookup ("a") != NULL; + + if (has_a_ext != list_has_a_ext) + return 0; + + + /* list must be subset of current this list, otherwise it not safe to + link. + TODO: We might give different weight for each extension, but the rule could + be complicated. + TODO: We might consider the version of each extension. */ + for (s = list->m_head; s != NULL; s = s->next) + if (this->lookup (s->name.c_str ()) != NULL) + score++; + else + return 0; + + return score; +} + /* Get the rank for single-letter subsets, lower value meaning higher priority. */ @@ -1305,6 +1362,326 @@ riscv_expand_arch_from_cpu (int argc ATTRIBUTE_UNUSED, return xasprintf ("-march=%s", arch.c_str()); } +/* Find last switch with the prefix, options are take last one in general, + return NULL if not found, and return the option value if found, it could + return empty string if the option has no value. */ + +static const char * +find_last_appear_switch ( + const struct switchstr *switches, + int n_switches, + const char *prefix) +{ + int i; + size_t len = strlen (prefix); + + for (i = 0; i < n_switches; ++i) + { + const struct switchstr *this_switch = &switches[n_switches - i - 1]; + + if (this_switch->live_cond & SWITCH_FALSE) + continue; + + if (strncmp (this_switch->part1, prefix, len) == 0) + return this_switch->part1 + len; + } + + return NULL; +} + +/* Utils functions to check STR is start with PREFIX or not. */ + +static bool +prefixed_with (const std::string &str, const char *prefix) +{ + return strncmp (prefix, str.c_str (), strlen (prefix)) == 0; +} + +/* Parse the path and cond string into riscv_multi_lib_info_t, return false + if parsing failed. */ + +bool +riscv_multi_lib_info_t::parse ( + struct riscv_multi_lib_info_t *multi_lib_info, + const std::string &path, + const std::vector<std::string> &conds) +{ + const char *default_arch_str = STRINGIZING (TARGET_RISCV_DEFAULT_ARCH); + const char *default_abi_str = STRINGIZING (TARGET_RISCV_DEFAULT_ABI); + multi_lib_info->conds = conds; + if (path == ".") + { + multi_lib_info->arch_str = default_arch_str; + multi_lib_info->abi_str = default_abi_str; + } + else + { + std::vector<std::string>::const_iterator itr; + for (itr = conds.begin (); itr != conds.end (); ++itr) + if (prefixed_with (*itr, "march=")) + multi_lib_info->arch_str = itr->c_str () + strlen ("march="); + else if (prefixed_with (*itr, "mabi=")) + multi_lib_info->abi_str = itr->c_str () + strlen ("mabi="); + + /* Skip this multi-lib if this configuration is exactly same as + default multi-lib settings. */ + if (multi_lib_info->arch_str == default_arch_str + && multi_lib_info->abi_str == default_abi_str) + return false; + } + + multi_lib_info->subset_list = + riscv_subset_list::parse (multi_lib_info->arch_str.c_str (), input_location); + + return true; +} + +/* Report error if not found suitable multilib. */ +const char * +riscv_multi_lib_check (int argc ATTRIBUTE_UNUSED, + const char **argv ATTRIBUTE_UNUSED) +{ + if (riscv_no_matched_multi_lib) + fatal_error ( + input_location, + "Can't find suitable multilib set for %<-march=%s%>/%<-mabi=%s%>", + riscv_current_arch_str.c_str (), + riscv_current_abi_str.c_str ()); + + return ""; +} + +/* Checking ARG is not appeared in SWITCHES if NOT_ARG is set or + ARG is appeared if NOT_ARG is not set. */ + +static bool +riscv_check_cond ( + const struct switchstr *switches, + int n_switches, + const std::string &arg, + bool not_arg) +{ + int i; + for (i = 0; i < n_switches; ++i) + { + const struct switchstr *this_switch = &switches[n_switches - i - 1]; + + if ((this_switch->live_cond & SWITCH_IGNORE) != 0) + continue; + + if (this_switch->live_cond & SWITCH_FALSE) + continue; + + /* ARG should not appear if NOT_ARG is set. */ + if (arg == this_switch->part1) + return not_arg ? false : true; + } + + /* Not found ARG? that's ok if NOT_ARG is not set. */ + return not_arg ? true : false; +} + +/* Check the other cond is found or not, return -1 if we should reject this + multi-lib option set, otherwise return updated MATCH_SCORE. */ + +static int +riscv_check_conds ( + const struct switchstr *switches, + int n_switches, + int match_score, + const std::vector<std::string> &conds) +{ + bool not_arg; + bool ok; + int ok_count = 0; + std::vector<std::string>::const_iterator itr; + const char *checking_arg; + + if (match_score == 0) + return 0; + + for (itr = conds.begin (); itr != conds.end (); ++itr) + { + /* We'll check march= and mabi= in ohter place. */ + if (prefixed_with (*itr, "march=") || prefixed_with (*itr, "mabi=")) + continue; + + checking_arg = itr->c_str (); + if (checking_arg[0] == '!') + { + not_arg = true; + /* Skip '!'. */ + checking_arg = checking_arg + 1; + } + else + not_arg = false; + + ok = riscv_check_cond (switches, n_switches, checking_arg, not_arg); + + if (!ok) + return -1; + + ok_count++; + } + + /* 100 is magic number, it's just used for make sure this multi-lib has + higher priority if we found any some option is listed in the option check + list. */ + return match_score + ok_count * 100; +} + +/* We only override this in bare-metal toolchain. */ +#ifdef RISCV_USE_CUSTOMISED_MULTI_LIB + +/* Implement TARGET_COMPUTE_MULTILIB. */ +static const char * +riscv_compute_multilib ( + const struct switchstr *switches, + int n_switches, + const char *multilib_dir, + const char *multilib_defaults ATTRIBUTE_UNUSED, + const char *multilib_select, + const char *multilib_matches ATTRIBUTE_UNUSED, + const char *multilib_exclusions ATTRIBUTE_UNUSED, + const char *multilib_reuse ATTRIBUTE_UNUSED) +{ + const char *p; + const char *this_path; + size_t this_path_len; + bool result; + riscv_no_matched_multi_lib = false; + riscv_subset_list *subset_list = NULL; + + std::vector<riscv_multi_lib_info_t> multilib_infos; + std::vector<std::string> option_conds; + std::string option_cond; + riscv_multi_lib_info_t multilib_info; + + /* Already found suitable, multi-lib, just use that. */ + if (multilib_dir != NULL) + return multilib_dir; + + /* Find march. */ + riscv_current_arch_str = + find_last_appear_switch (switches, n_switches, "march="); + /* Find mabi. */ + riscv_current_abi_str = + find_last_appear_switch (switches, n_switches, "mabi="); + + /* Failed to find -march or -mabi, but it should not happened since we have + set both in OPTION_DEFAULT_SPECS. */ + if (riscv_current_arch_str.empty () || riscv_current_abi_str.empty ()) + return multilib_dir; + + subset_list = riscv_subset_list::parse (riscv_current_arch_str.c_str (), + input_location); + + /* Failed to parse -march, fallback to using what gcc use. */ + if (subset_list == NULL) + return multilib_dir; + + /* Parsing MULTILIB_SELECT, ignore MULTILIB_REUSE here, we have our own rules. + TODO: most codes are grab from gcc.c, maybe we should refine that? */ + p = multilib_select; + + while (*p != '\0') + { + /* Ignore newlines. */ + if (*p == '\n') + { + ++p; + continue; + } + + /* Format of each multilib: + <path> <opt1> <opt2> ... <optN>; */ + /* Get the path. */ + this_path = p; + while (*p != ' ') + { + if (*p == '\0') + { + fatal_error (input_location, "multilib select %qs %qs is invalid", + multilib_select, multilib_reuse); + } + ++p; + } + + this_path_len = p - this_path; + multilib_info.path = std::string (this_path, this_path_len); + + option_conds.clear (); + /* Pasrse option check list into vector<string>. + e.g. "march=rv64imafd mabi=lp64 !mcmodel=medany" to + ["march=rv64imafd", "mabi=lp64", "!mcmodel=medany"]. */ + while (*p != ';') + { + option_cond = ""; + /* Skip space. */ + while (*p == ' ') p++; + + while (*p && *p != ' ' && *p != ';') + option_cond.push_back (*p++); + + /* Ignore `!march=` and `!mabi=`, we will handle march and mabi + later. */ + if (option_cond.size () + && !prefixed_with (option_cond, "!march=") + && !prefixed_with (option_cond, "!mabi=")) + option_conds.push_back (option_cond); + } + + result = + riscv_multi_lib_info_t::parse ( + &multilib_info, + std::string (this_path, this_path_len), + option_conds); + + if (result) + multilib_infos.push_back (multilib_info); + + p++; + } + + int match_score = 0; + int max_match_score = 0; + int best_match_multi_lib = -1; + /* Try to decision which set we should used. */ + /* We have 3 level decision tree here, ABI, check input arch/ABI must + be superset of multi-lib arch, and other rest option checking. */ + for (size_t i = 0; i < multilib_infos.size (); ++i) + { + /* Check ABI is same first. */ + if (riscv_current_abi_str != multilib_infos[i].abi_str) + continue; + + /* Found a potential compatible multi-lib setting! + Calculate the match score. */ + match_score = subset_list->match_score (multilib_infos[i].subset_list); + + /* Checking other cond in the multi-lib setting. */ + match_score = riscv_check_conds (switches, + n_switches, + match_score, + multilib_infos[i].conds); + + /* Record highest match score multi-lib setting. */ + if (match_score > max_match_score) + best_match_multi_lib = i; + } + + if (best_match_multi_lib == -1) + { + riscv_no_matched_multi_lib = true; + return multilib_dir; + } + else + return xstrdup (multilib_infos[best_match_multi_lib].path.c_str ()); +} + +#undef TARGET_COMPUTE_MULTILIB +#define TARGET_COMPUTE_MULTILIB riscv_compute_multilib +#endif /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ static const struct default_options riscv_option_optimization_table[] = diff --git a/gcc/common/config/s390/s390-common.cc b/gcc/common/config/s390/s390-common.cc index 72a5ef4..be3e6f2 100644 --- a/gcc/common/config/s390/s390-common.cc +++ b/gcc/common/config/s390/s390-common.cc @@ -64,6 +64,11 @@ static const struct default_options s390_option_optimization_table[] = /* Enable -fsched-pressure by default when optimizing. */ { OPT_LEVELS_1_PLUS, OPT_fsched_pressure, NULL, 1 }, + /* Enable -munroll-only-small-loops with -funroll-loops to unroll small + loops at -O2 and above by default. */ + { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_funroll_loops, NULL, 1 }, + { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_munroll_only_small_loops, NULL, 1 }, + /* ??? There are apparently still problems with -fcaller-saves. */ { OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 }, diff --git a/gcc/config.build b/gcc/config.build index 30559b9..eb3bfbf 100644 --- a/gcc/config.build +++ b/gcc/config.build @@ -50,10 +50,7 @@ build_file_translate= # System-specific settings. case $build in - hppa1.0-*-hpux1[01]* | \ - hppa*64*-*-hpux11* | \ - hppa1.1-*-hpux11* | \ - hppa2*-*-hpux11* ) + hppa*64*-*-hpux11* ) build_install_headers_dir=install-headers-cpio ;; i[34567]86-*-cygwin* | x86_64-*-cygwin* ) diff --git a/gcc/config.gcc b/gcc/config.gcc index 02f5897..f4e757b 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -72,10 +72,10 @@ # tm_file A list of target macro files, if different from # "$cpu_type/$cpu_type.h". Usually it's constructed # per target in a way like this: -# tm_file="${tm_file} dbxelf.h elfos.h ${cpu_type.h}/elf.h" +# tm_file="${tm_file} elfos.h ${cpu_type.h}/elf.h" # Note that the preferred order is: # - specific target header "${cpu_type}/${cpu_type.h}" -# - generic headers like dbxelf.h elfos.h, etc. +# - generic headers like elfos.h, etc. # - specializing target headers like ${cpu_type.h}/elf.h # This helps to keep OS specific stuff out of the CPU # defining header ${cpu_type}/${cpu_type.h}. @@ -248,10 +248,9 @@ md_file= # Obsolete configurations. case ${target} in - cr16-*-* \ - | hppa[12]*-*-hpux10* \ - | hppa[12]*-*-hpux11* \ - | m32c-*-rtems* \ + *) + ;; + obsoleted-target \ ) if test "x$enable_obsolete" != xyes; then echo "*** Configuration ${target} is obsolete." >&2 @@ -559,11 +558,15 @@ xtensa*-*-*) esac tm_file=${cpu_type}/${cpu_type}.h -tm_d_file=${cpu_type}/${cpu_type}.h if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-protos.h then tm_p_file=${cpu_type}/${cpu_type}-protos.h - tm_d_file="${tm_d_file} ${cpu_type}/${cpu_type}-protos.h" +fi + +tm_d_file= +if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-d.h +then + tm_d_file="${tm_d_file} ${cpu_type}/${cpu_type}-d.h" fi extra_modes= @@ -669,7 +672,6 @@ case ${target} in *-*-darwin*) tmake_file="t-darwin " tm_file="${tm_file} darwin.h" - tm_d_file="${tm_d_file} tm-dwarf2.h" darwin_os=`echo ${target} | sed 's/.*darwin\([0-9.]*\).*$/\1/'` darwin_maj=`expr "$darwin_os" : '\([0-9]*\).*'` macos_min=`expr "$darwin_os" : '[0-9]*\.\([0-9]*\).*'` @@ -957,7 +959,7 @@ case ${target} in *-*-solaris2*) # i?86-*-solaris2* needs to insert headers between cpu default and # Solaris 2 specific ones. - sol2_tm_file_head="dbxelf.h elfos.h ${cpu_type}/sysv4.h" + sol2_tm_file_head="elfos.h ${cpu_type}/sysv4.h" sol2_tm_file_tail="${cpu_type}/sol2.h sol2.h" sol2_tm_file="${sol2_tm_file_head} ${sol2_tm_file_tail}" case ${target} in @@ -1081,7 +1083,7 @@ esac case ${target} in aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h" + tm_file="${tm_file} elfos.h newlib-stdint.h" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h" tmake_file="${tmake_file} aarch64/t-aarch64" case $target in @@ -1118,19 +1120,19 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*) TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'` ;; aarch64*-*-freebsd*) - tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file}" + tm_file="${tm_file} elfos.h ${fbsd_tm_file}" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h" tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-freebsd" tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1" ;; aarch64*-*-netbsd*) - tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file}" + tm_file="${tm_file} elfos.h ${nbsd_tm_file}" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-netbsd.h" tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-netbsd" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" ;; aarch64*-*-linux*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-linux.h" tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-linux" tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1" @@ -1186,7 +1188,7 @@ alpha*-dec-*vms*) tmake_file="${tmake_file} alpha/t-vms alpha/t-alpha" ;; arc*-*-elf*) - tm_file="arc/arc-arch.h dbxelf.h elfos.h newlib-stdint.h arc/elf.h ${tm_file}" + tm_file="arc/arc-arch.h elfos.h newlib-stdint.h arc/elf.h ${tm_file}" tmake_file="arc/t-multilib arc/t-arc" extra_gcc_objs="driver-arc.o" if test "x$with_cpu" != x; then @@ -1207,7 +1209,7 @@ arc*-*-elf*) esac ;; arc*-*-linux*) - tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}" + tm_file="arc/arc-arch.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}" tmake_file="${tmake_file} arc/t-multilib-linux arc/t-arc" extra_gcc_objs="driver-arc.o" if test "x$with_cpu" != x; then @@ -1243,7 +1245,7 @@ arm-wrs-vxworks7*) need_64bit_hwint=yes ;; arm*-*-freebsd*) # ARM FreeBSD EABI - tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h" + tm_file="elfos.h ${fbsd_tm_file} arm/elf.h" case $target in arm*b-*-freebsd*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" @@ -1271,7 +1273,7 @@ arm*-*-freebsd*) # ARM FreeBSD EABI arm*-*-netbsdelf*) target_cpu_cname="strongarm" tmake_file="${tmake_file} arm/t-arm" - tm_file="dbxelf.h elfos.h ${nbsd_tm_file} arm/elf.h" + tm_file="elfos.h ${nbsd_tm_file} arm/elf.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" case ${target} in arm*eb-*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" ;; @@ -1300,7 +1302,7 @@ arm*-*-netbsdelf*) esac ;; arm*-*-linux-* | arm*-*-uclinuxfdpiceabi) - tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h" + tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h" extra_options="${extra_options} linux-android.opt" case $target in arm*b-*-linux*) @@ -1338,7 +1340,7 @@ arm*-*-linux-* | arm*-*-uclinuxfdpiceabi) with_tls=${with_tls:-gnu} ;; arm*-*-uclinux*eabi*) # ARM ucLinux - tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h" + tm_file="elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h" tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi" tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h arm/aout.h arm/arm.h" target_cpu_cname="arm7tdmi" @@ -1358,7 +1360,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" esac default_use_cxa_atexit=yes - tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h" + tm_file="elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h" tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf" target_cpu_cname="arm7tdmi" case ${target} in @@ -1387,7 +1389,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*) tm_file="${tm_file} arm/aout.h arm/arm.h" ;; avr-*-*) - tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h dbxelf.h avr/avr-stdint.h" + tm_file="elfos.h avr/elf.h avr/avr-arch.h avr/avr.h avr/specs.h avr/avr-stdint.h" if test x${with_avrlibc} != xno; then tm_file="${tm_file} ${cpu_type}/avrlibc.h" tm_defines="${tm_defines} WITH_AVRLIBC" @@ -1520,26 +1522,26 @@ avr-*-*) extra_objs="avr-devices.o avr-log.o" ;; bfin*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h" + tm_file="${tm_file} elfos.h newlib-stdint.h bfin/elf.h" tmake_file=bfin/t-bfin-elf use_collect2=no ;; bfin*-uclinux*) - tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/uclinux.h" + tm_file="${tm_file} elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/uclinux.h" tmake_file=bfin/t-bfin-uclinux use_collect2=no ;; bfin*-linux-uclibc*) - tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/linux.h ./linux-sysroot-suffix.h" + tm_file="${tm_file} elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/linux.h ./linux-sysroot-suffix.h" tmake_file="${tmake_file} bfin/t-bfin-linux" use_collect2=no ;; bfin*-rtems*) - tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h bfin/rtems.h rtems.h newlib-stdint.h" + tm_file="${tm_file} elfos.h bfin/elf.h bfin/rtems.h rtems.h newlib-stdint.h" tmake_file="${tmake_file} bfin/t-rtems" ;; bfin*-*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h" + tm_file="${tm_file} elfos.h newlib-stdint.h bfin/elf.h" use_collect2=no use_gcc_stdint=wrap ;; @@ -1552,11 +1554,6 @@ bpf-*-*) extra_objs="coreout.o" target_gtfiles="$target_gtfiles \$(srcdir)/config/bpf/coreout.cc" ;; -cr16-*-elf) - tm_file="elfos.h ${tm_file} newlib-stdint.h" - tmake_file="${tmake_file} cr16/t-cr16 " - use_collect2=no - ;; cris-*-elf | cris-*-none) tm_file="elfos.h newlib-stdint.h ${tm_file}" tmake_file="cris/t-cris cris/t-elfmulti" @@ -1595,13 +1592,13 @@ csky-*-*) case ${target} in csky-*-elf*) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} csky/csky-elf.h" + tm_file="elfos.h newlib-stdint.h ${tm_file} csky/csky-elf.h" tmake_file="csky/t-csky csky/t-csky-elf" default_use_cxa_atexit=no use_gcc_stdint=wrap ;; csky-*-linux*) - tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} csky/csky-linux-elf.h" + tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} csky/csky-linux-elf.h" tmake_file="${tmake_file} csky/t-csky csky/t-csky-linux" case ${target} in @@ -1628,7 +1625,7 @@ csky-*-*) esac ;; epiphany-*-elf | epiphany-*-rtems*) - tm_file="dbxelf.h elfos.h ${tm_file}" + tm_file="elfos.h ${tm_file}" tmake_file="${tmake_file} epiphany/t-epiphany" case ${target} in epiphany-*-rtems*) @@ -1644,21 +1641,21 @@ epiphany-*-elf | epiphany-*-rtems*) extra_headers="epiphany_intrinsics.h" ;; fr30-*-elf) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" ;; frv-*-elf) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" tmake_file=frv/t-frv ;; frv-*-*linux*) - tm_file="dbxelf.h elfos.h ${tm_file} \ + tm_file="elfos.h ${tm_file} \ gnu-user.h linux.h glibc-stdint.h frv/linux.h" tmake_file="${tmake_file} frv/t-frv frv/t-linux" ;; ft32-*-elf) gas=yes gnu_ld=yes - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" tmake_file="${tmake_file} ft32/t-ft32" ;; amdgcn-*-amdhsa) @@ -1686,23 +1683,23 @@ amdgcn-*-amdhsa) moxie-*-elf) gas=yes gnu_ld=yes - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" tmake_file="${tmake_file} moxie/t-moxie" ;; moxie-*-uclinux*) gas=yes gnu_ld=yes - tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h moxie/uclinux.h" + tm_file="elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h moxie/uclinux.h" tmake_file="${tmake_file} moxie/t-moxie" ;; moxie-*-rtems*) tmake_file="${tmake_file} moxie/t-moxie" - tm_file="moxie/moxie.h dbxelf.h elfos.h moxie/rtems.h rtems.h newlib-stdint.h" + tm_file="moxie/moxie.h elfos.h moxie/rtems.h rtems.h newlib-stdint.h" ;; moxie-*-moxiebox*) gas=yes gnu_ld=yes - tm_file="${tm_file} dbxelf.h elfos.h moxie/moxiebox.h newlib-stdint.h" + tm_file="${tm_file} elfos.h moxie/moxiebox.h newlib-stdint.h" tmake_file="${tmake_file} moxie/t-moxiebox" ;; h8300-*-elf*) @@ -1715,7 +1712,7 @@ h8300-*-linux*) ;; hppa*64*-*-linux*) target_cpu_default="MASK_PA_11|MASK_PA_20" - tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h gnu-user.h linux.h \ + tm_file="pa/pa64-start.h ${tm_file} elfos.h gnu-user.h linux.h \ glibc-stdint.h pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h \ pa/pa64-linux.h" tmake_file="${tmake_file} pa/t-pa pa/t-linux" @@ -1724,14 +1721,14 @@ hppa*64*-*-linux*) ;; hppa*-*-linux*) target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS|MASK_CALLER_COPIES" - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h pa/pa-linux.h \ + tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h pa/pa-linux.h \ pa/pa32-regs.h pa/pa32-linux.h" tmake_file="${tmake_file} pa/t-pa pa/t-linux" d_target_objs="${d_target_objs} pa-d.o" ;; hppa*-*-openbsd*) target_cpu_default="MASK_PA_11" - tm_file="${tm_file} dbxelf.h elfos.h openbsd.h openbsd-stdint.h openbsd-libpthread.h \ + tm_file="${tm_file} elfos.h openbsd.h openbsd-stdint.h openbsd-libpthread.h \ pa/pa-openbsd.h pa/pa32-regs.h pa/pa32-openbsd.h" extra_options="${extra_options} openbsd.opt" tmake_file="pa/t-pa" @@ -1741,55 +1738,19 @@ hppa*-*-openbsd*) ;; hppa*-*-netbsd*) target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS" - tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file} \ + tm_file="${tm_file} elfos.h ${nbsd_tm_file} \ pa/pa-netbsd.h pa/pa32-regs.h pa/pa32-netbsd.h" tmake_file="${tmake_file}" tm_defines="${tm_defines} CHAR_FAST8=1 SHORT_FAST16=1" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" ;; -hppa[12]*-*-hpux10*) - case ${target} in - hppa1.1-*-* | hppa2*-*-*) - target_cpu_default="MASK_PA_11" - ;; - esac - tm_file="${tm_file} pa/pa32-regs.h dbxelf.h pa/som.h \ - pa/pa-hpux.h pa/pa-hpux10.h" - extra_options="${extra_options} pa/pa-hpux.opt pa/pa-hpux10.opt" - case ${target} in - *-*-hpux10.[1-9]*) - tm_file="${tm_file} pa/pa-hpux1010.h" - extra_options="${extra_options} pa/pa-hpux1010.opt" - ;; - esac - use_gcc_stdint=provide - tm_file="${tm_file} hpux-stdint.h" - tmake_file="pa/t-pa t-slibgcc" - d_target_objs="${d_target_objs} pa-d.o" - case ${enable_threads} in - "") - if test x$have_pthread_h = xyes ; then - tmake_file="${tmake_file} pa/t-dce-thr" - fi - ;; - yes | dce) - tmake_file="${tmake_file} pa/t-dce-thr" - ;; - esac - use_collect2=yes - gas=yes - if test "x$with_dwarf2" != x; then - echo "Warning: dwarf2 debug format is not supported for this target, --with-dwarf2 ignored" 1>&2 - dwarf2=no - fi - ;; hppa*64*-*-hpux11*) target_cpu_default="MASK_PA_11|MASK_PA_20" if test x$gnu_ld = xyes then target_cpu_default="${target_cpu_default}|MASK_GNU_LD" fi - tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h \ + tm_file="pa/pa64-start.h ${tm_file} elfos.h \ pa/pa64-regs.h pa/pa-hpux.h pa/pa-hpux1010.h \ pa/pa-hpux11.h" case ${target} in @@ -1826,50 +1787,6 @@ hppa*64*-*-hpux11*) ;; esac ;; -hppa[12]*-*-hpux11*) - case ${target} in - hppa1.1-*-* | hppa2*-*-*) - target_cpu_default="MASK_PA_11" - ;; - esac - tm_file="${tm_file} pa/pa32-regs.h dbxelf.h pa/som.h \ - pa/pa-hpux.h pa/pa-hpux1010.h pa/pa-hpux11.h" - extra_options="${extra_options} pa/pa-hpux.opt pa/pa-hpux1010.opt \ - hpux11.opt" - case ${target} in - *-*-hpux11.[12]*) - tm_file="${tm_file} pa/pa-hpux1111.h" - extra_options="${extra_options} pa/pa-hpux1111.opt" - ;; - *-*-hpux11.[3-9]*) - tm_file="${tm_file} pa/pa-hpux1131.h" - extra_options="${extra_options} pa/pa-hpux1131.opt" - ;; - esac - tmake_file="pa/t-pa t-slibgcc" - d_target_objs="${d_target_objs} pa-d.o" - case x${enable_threads} in - x | xyes | xposix ) - thread_file=posix - ;; - esac - use_collect2=yes - gas=yes - case ${target} in - *-*-hpux11.[01]*) - use_gcc_stdint=provide - tm_file="${tm_file} hpux-stdint.h" - ;; - *-*-hpux11.[23]*) - use_gcc_stdint=wrap - tm_file="${tm_file} hpux-stdint.h" - ;; - esac - if test "x$with_dwarf2" != x; then - echo "Warning: dwarf2 debug format is not supported for this target, --with-dwarf2 ignored" 1>&2 - dwarf2=no - fi - ;; i[34567]86-*-darwin1[89]* | i[34567]86-*-darwin2*) echo "Error: 32bit target is not supported after Darwin17" 1>&2 ;; @@ -1893,55 +1810,55 @@ x86_64-*-darwin*) tm_file="${cpu_type}/darwin64-biarch.h ${tm_file} " ;; i[34567]86-*-elfiamcu) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/iamcu.h" ;; i[34567]86-*-elf*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h" ;; x86_64-*-elf*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" ;; x86_64-*-rtems*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rtemself.h rtems.h" ;; i[34567]86-*-rdos*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h" ;; x86_64-*-rdos*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rdos.h i386/rdos64.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h i386/rdos.h i386/rdos64.h" tmake_file="i386/t-i386elf t-svr4" ;; i[34567]86-*-dragonfly*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/dragonfly.h" tmake_file="${tmake_file} i386/t-crtstuff" ;; x86_64-*-dragonfly*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h dragonfly.h dragonfly-stdint.h i386/x86-64.h i386/dragonfly.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h dragonfly.h dragonfly-stdint.h i386/x86-64.h i386/dragonfly.h" tmake_file="${tmake_file} i386/t-crtstuff" ;; i[34567]86-*-freebsd*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${fbsd_tm_file} i386/freebsd.h" ;; x86_64-*-freebsd*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h" ;; i[34567]86-*-netbsdelf*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${nbsd_tm_file} i386/netbsd-elf.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${nbsd_tm_file} i386/netbsd-elf.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" ;; x86_64-*-netbsd*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${nbsd_tm_file} i386/x86-64.h i386/netbsd64.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h ${nbsd_tm_file} i386/x86-64.h i386/netbsd64.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" ;; i[34567]86-*-openbsd*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h" tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h i386/openbsdelf.h" extra_options="${extra_options} openbsd.opt" gas=yes gnu_ld=yes ;; x86_64-*-openbsd*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h" tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h i386/x86-64.h i386/openbsdelf.h" extra_options="${extra_options} openbsd.opt" gas=yes @@ -1950,7 +1867,7 @@ x86_64-*-openbsd*) i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu) # Intel 80386's running GNU/* # with ELF format using glibc 2 - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h gnu-user.h glibc-stdint.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h gnu-user.h glibc-stdint.h" case ${target} in i[34567]86-*-linux*) tm_file="${tm_file} linux.h linux-android.h" @@ -2007,7 +1924,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]8 esac ;; x86_64-*-linux* | x86_64-*-kfreebsd*-gnu) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h gnu-user.h glibc-stdint.h \ + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h gnu-user.h glibc-stdint.h \ i386/x86-64.h i386/gnu-user-common.h i386/gnu-user64.h" case ${target} in x86_64-*-linux*) @@ -2045,7 +1962,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu) ;; i[34567]86-pc-msdosdjgpp*) xm_file=i386/xm-djgpp.h - tm_file="dbxcoff.h ${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h" + tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h" native_system_header_dir=/dev/env/DJDIR/include extra_options="${extra_options} i386/djgpp.opt" gnu_ld=yes @@ -2054,7 +1971,7 @@ i[34567]86-pc-msdosdjgpp*) ;; i[34567]86-*-lynxos*) xm_defines=POSIX - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/lynx.h lynx.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/lynx.h lynx.h" tmake_file="${tmake_file} t-lynx" extra_options="${extra_options} lynx.opt" thread_file=lynx @@ -2062,13 +1979,13 @@ i[34567]86-*-lynxos*) gas=yes ;; i[34567]86-*-nto-qnx*) - tm_file="${tm_file} i386/att.h dbxelf.h tm-dwarf2.h elfos.h i386/unix.h i386/nto.h" + tm_file="${tm_file} i386/att.h tm-dwarf2.h elfos.h i386/unix.h i386/nto.h" extra_options="${extra_options} i386/nto.opt" gnu_ld=yes gas=yes ;; i[34567]86-*-rtems*) - tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h newlib-stdint.h" + tm_file="${tm_file} i386/unix.h i386/att.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h newlib-stdint.h" tmake_file="${tmake_file} i386/t-rtems" ;; i[34567]86-*-solaris2* | x86_64-*-solaris2*) @@ -2117,7 +2034,7 @@ i[4567]86-wrs-vxworks*|x86_64-wrs-vxworks7*) esac ;; i[34567]86-*-cygwin*) - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h" + tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h" xm_file=i386/xm-cygwin.h tmake_file="${tmake_file} i386/t-cygming t-slibgcc" target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc" @@ -2135,7 +2052,7 @@ i[34567]86-*-cygwin*) ;; x86_64-*-cygwin*) need_64bit_isa=yes - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-w64.h i386/cygwin-stdint.h" + tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h i386/cygwin.h i386/cygwin-w64.h i386/cygwin-stdint.h" xm_file=i386/xm-cygwin.h tmake_file="${tmake_file} i386/t-cygming t-slibgcc i386/t-cygwin-w64" target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc" @@ -2153,7 +2070,7 @@ x86_64-*-cygwin*) tm_defines="${tm_defines} TARGET_CYGWIN64=1" ;; i[34567]86-*-mingw* | x86_64-*-mingw*) - tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h" + tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/cygming.h" xm_file=i386/xm-mingw32.h c_target_objs="${c_target_objs} winnt-c.o" cxx_target_objs="${cxx_target_objs} winnt-c.o" @@ -2247,7 +2164,7 @@ x86_64-*-fuchsia*) tm_file="${tm_file} i386/unix.h i386/att.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h fuchsia.h" ;; ia64*-*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h ia64/sysv4.h ia64/elf.h" + tm_file="${tm_file} elfos.h newlib-stdint.h ia64/sysv4.h ia64/elf.h" tmake_file="ia64/t-ia64" target_cpu_default="0" if test x$gas = xyes @@ -2260,17 +2177,17 @@ ia64*-*-elf*) fi ;; ia64*-*-freebsd*) - tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file} ia64/sysv4.h ia64/freebsd.h" + tm_file="${tm_file} elfos.h ${fbsd_tm_file} ia64/sysv4.h ia64/freebsd.h" target_cpu_default="MASK_GNU_AS|MASK_GNU_LD" tmake_file="${tmake_file} ia64/t-ia64" ;; ia64*-*-linux*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h" tmake_file="${tmake_file} ia64/t-ia64 ia64/t-linux t-libunwind" target_cpu_default="MASK_GNU_AS|MASK_GNU_LD" ;; ia64*-*-hpux*) - tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/hpux.h" + tm_file="${tm_file} elfos.h ia64/sysv4.h ia64/hpux.h" tmake_file="ia64/t-ia64 ia64/t-hpux t-slibgcc" target_cpu_default="MASK_GNU_AS" case x$enable_threads in @@ -2306,16 +2223,16 @@ iq2000*-*-elf*) md_file=iq2000/iq2000.md ;; lm32-*-elf*) - tm_file="dbxelf.h elfos.h ${tm_file} newlib-stdint.h" + tm_file="elfos.h ${tm_file} newlib-stdint.h" tmake_file="${tmake_file} lm32/t-lm32" ;; lm32-*-rtems*) - tm_file="dbxelf.h elfos.h ${tm_file} lm32/rtems.h rtems.h newlib-stdint.h" + tm_file="elfos.h ${tm_file} lm32/rtems.h rtems.h newlib-stdint.h" tmake_file="${tmake_file} lm32/t-lm32" tmake_file="${tmake_file} lm32/t-rtems" ;; lm32-*-uclinux*) - tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h lm32/uclinux-elf.h" + tm_file="elfos.h ${tm_file} gnu-user.h linux.h lm32/uclinux-elf.h" tmake_file="${tmake_file} lm32/t-lm32" ;; m32r-*-elf*) @@ -2343,7 +2260,7 @@ m68k-*-elf* | fido-*-elf*) default_cf_cpu=5206 ;; esac - tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h" + tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h" tm_defines="${tm_defines} MOTOROLA=1" tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf" # Add multilibs for targets other than fido. @@ -2358,7 +2275,7 @@ m68k-*-elf* | fido-*-elf*) m68k*-*-netbsdelf*) default_m68k_cpu=68020 default_cf_cpu=5475 - tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file} m68k/netbsd-elf.h" + tm_file="${tm_file} elfos.h ${nbsd_tm_file} m68k/netbsd-elf.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" tm_defines="${tm_defines} MOTOROLA=1 CHAR_FAST8=1 SHORT_FAST16=1" ;; @@ -2367,7 +2284,7 @@ m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux # ABI. default_m68k_cpu=68020 default_cf_cpu=5206 - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h flat.h m68k/linux.h m68k/uclinux.h ./sysroot-suffix.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h flat.h m68k/linux.h m68k/uclinux.h ./sysroot-suffix.h" extra_options="${extra_options} m68k/uclinux.opt" tm_defines="${tm_defines} MOTOROLA=1" tmake_file="m68k/t-floatlib m68k/t-uclinux m68k/t-mlibs" @@ -2378,7 +2295,7 @@ m68k-*-linux*) # Motorola m68k's running GNU/Linux default_m68k_cpu=68020 default_cf_cpu=5475 with_arch=${with_arch:-m68k} - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h m68k/linux.h ./sysroot-suffix.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h m68k/linux.h ./sysroot-suffix.h" extra_options="${extra_options} m68k/ieee.opt" tm_defines="${tm_defines} MOTOROLA=1" tmake_file="${tmake_file} m68k/t-floatlib m68k/t-linux m68k/t-mlibs" @@ -2387,11 +2304,11 @@ m68k-*-rtems*) default_m68k_cpu=68020 default_cf_cpu=5206 tmake_file="${tmake_file} m68k/t-floatlib m68k/t-m68kbare m68k/t-crtstuff m68k/t-rtems m68k/t-mlibs" - tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h m68k/rtemself.h rtems.h newlib-stdint.h" + tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h m68k/rtemself.h rtems.h newlib-stdint.h" tm_defines="${tm_defines} MOTOROLA=1" ;; mcore-*-elf) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h" + tm_file="elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h" tmake_file=mcore/t-mcore inhibit_libc=true ;; @@ -2404,7 +2321,7 @@ microblaze*-linux*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321" ;; esac - tm_file="${tm_file} dbxelf.h gnu-user.h linux.h microblaze/linux.h" + tm_file="${tm_file} gnu-user.h linux.h microblaze/linux.h" tm_file="${tm_file} glibc-stdint.h" c_target_objs="${c_target_objs} microblaze-c.o" cxx_target_objs="${cxx_target_objs} microblaze-c.o" @@ -2420,7 +2337,7 @@ microblaze*-*-rtems*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321" ;; esac - tm_file="${tm_file} dbxelf.h" + tm_file="${tm_file}" tm_file="${tm_file} microblaze/rtems.h rtems.h newlib-stdint.h" c_target_objs="${c_target_objs} microblaze-c.o" cxx_target_objs="${cxx_target_objs} microblaze-c.o" @@ -2436,7 +2353,7 @@ microblaze*-*-elf) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321" ;; esac - tm_file="${tm_file} dbxelf.h newlib-stdint.h" + tm_file="${tm_file} newlib-stdint.h" c_target_objs="${c_target_objs} microblaze-c.o" cxx_target_objs="${cxx_target_objs} microblaze-c.o" tmake_file="${tmake_file} microblaze/t-microblaze" @@ -2504,7 +2421,7 @@ riscv*-*-freebsd*) ;; loongarch*-*-linux*) - tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}" + tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}" tm_file="${tm_file} loongarch/gnu-user.h loongarch/linux.h" extra_options="${extra_options} linux-android.opt" tmake_file="${tmake_file} loongarch/t-linux" @@ -2522,7 +2439,7 @@ mips*-*-netbsd*) # NetBSD/mips, either endian. extra_options="${extra_options} netbsd.opt netbsd-elf.opt" ;; mips*-img-linux*) - tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h" + tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h" extra_options="${extra_options} linux-android.opt" tmake_file="${tmake_file} mips/t-img-linux" tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32" @@ -2532,7 +2449,7 @@ mips*-img-linux*) gas=yes ;; mips*-mti-linux*) - tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h" + tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h mips/mti-linux.h" extra_options="${extra_options} linux-android.opt" tmake_file="${tmake_file} mips/t-mti-linux" tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32" @@ -2542,7 +2459,7 @@ mips*-mti-linux*) gas=yes ;; mips*-*-linux*) # Linux MIPS, either endian. - tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h" + tm_file="elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h" extra_options="${extra_options} linux-android.opt" case ${target} in mipsisa32r6*) @@ -2754,7 +2671,7 @@ mn10300-*-*) use_gcc_stdint=wrap ;; msp430-*-*) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" c_target_objs="msp430-c.o" cxx_target_objs="msp430-c.o" tmake_file="${tmake_file} msp430/t-msp430" @@ -2792,11 +2709,11 @@ nds32*-*-*) esac case ${target} in nds32*-*-elf*) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} nds32/elf.h nds32/nds32_intrinsic.h" + tm_file="elfos.h newlib-stdint.h ${tm_file} nds32/elf.h nds32/nds32_intrinsic.h" tmake_file="nds32/t-nds32 nds32/t-elf" ;; nds32*-*-linux*) - tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h nds32/linux.h nds32/nds32_intrinsic.h" + tm_file="elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h nds32/linux.h nds32/nds32_intrinsic.h" tmake_file="${tmake_file} nds32/t-nds32 nds32/t-linux" gcc_cv_initfini_array=yes ;; @@ -2917,7 +2834,7 @@ powerpc64-*-darwin*) tm_file="${tm_file} ${cpu_type}/darwin64-biarch.h" ;; powerpc*-*-freebsd*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h ${fbsd_tm_file} rs6000/sysv4.h" + tm_file="${tm_file} elfos.h gnu-user.h ${fbsd_tm_file} rs6000/sysv4.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm" case ${target} in @@ -2942,47 +2859,47 @@ powerpc*-*-freebsd*) esac ;; powerpc-*-netbsd*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h ${nbsd_tm_file} freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h" + tm_file="${tm_file} elfos.h gnu-user.h ${nbsd_tm_file} freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" tmake_file="${tmake_file} rs6000/t-netbsd" extra_options="${extra_options} rs6000/sysv4.opt" ;; powerpc-*-eabisimaltivec*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h rs6000/eabialtivec.h" + tm_file="${tm_file} elfos.h gnu-user.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 gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h" + tm_file="${tm_file} elfos.h gnu-user.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 ;; powerpc-*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h" + tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" ;; powerpc-*-eabialtivec*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabialtivec.h" + tm_file="${tm_file} elfos.h gnu-user.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 ;; powerpc-*-eabi*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/eabi.h" + tm_file="${tm_file} elfos.h gnu-user.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 ;; powerpc-*-rtems*) - tm_file="rs6000/biarch64.h ${tm_file} dbxelf.h elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h" + tm_file="rs6000/biarch64.h ${tm_file} elfos.h gnu-user.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/rtems.h rtems.h" extra_options="${extra_options} rs6000/sysv4.opt rs6000/linux64.opt" tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-rtems rs6000/t-ppccomm" ;; powerpc*-*-linux*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h freebsd-spec.h rs6000/sysv4.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h freebsd-spec.h rs6000/sysv4.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-ppccomm" extra_objs="$extra_objs rs6000-linux.o" @@ -3089,7 +3006,7 @@ powerpc-wrs-vxworks*) ;; powerpc-*-lynxos*) xm_defines=POSIX - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h rs6000/sysv4.h rs6000/lynx.h lynx.h" + tm_file="${tm_file} elfos.h gnu-user.h rs6000/sysv4.h rs6000/lynx.h lynx.h" tmake_file="t-lynx rs6000/t-lynx" extra_options="${extra_options} rs6000/sysv4.opt lynx.opt" thread_file=lynx @@ -3097,18 +3014,18 @@ powerpc-*-lynxos*) gas=yes ;; powerpcle-*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h" + tm_file="${tm_file} elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h" tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm" extra_options="${extra_options} rs6000/sysv4.opt" ;; powerpcle-*-eabisim*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h rs6000/eabisim.h" + tm_file="${tm_file} elfos.h gnu-user.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 gnu-user.h usegas.h freebsd-spec.h newlib-stdint.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/eabi.h" + tm_file="${tm_file} elfos.h gnu-user.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 @@ -3166,7 +3083,7 @@ rl78-*-elf*) tmake_file="${tmake_file} rl78/t-rl78" ;; rx-*-elf*) - tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tm_file="elfos.h newlib-stdint.h ${tm_file}" tmake_file="${tmake_file} rx/t-rx" extra_options="${extra_options} rx/elf.opt" ;; @@ -3175,7 +3092,7 @@ rx-*-linux*) tmake_file="${tmake_file} rx/t-linux" ;; s390-*-linux*) - tm_file="s390/s390.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h" + tm_file="s390/s390.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h" c_target_objs="${c_target_objs} s390-c.o" cxx_target_objs="${cxx_target_objs} s390-c.o" if test x$enable_targets = xall; then @@ -3184,7 +3101,7 @@ s390-*-linux*) tmake_file="${tmake_file} s390/t-s390" ;; s390x-*-linux*) - tm_file="s390/s390x.h s390/s390.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h" + tm_file="s390/s390x.h s390/s390.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h" tm_p_file="linux-protos.h s390/s390-protos.h" c_target_objs="${c_target_objs} s390-c.o" cxx_target_objs="${cxx_target_objs} s390-c.o" @@ -3194,7 +3111,7 @@ s390x-*-linux*) tmake_file="${tmake_file} s390/t-linux64 s390/t-s390" ;; s390x-ibm-tpf*) - tm_file="s390/s390x.h s390/s390.h dbxelf.h elfos.h glibc-stdint.h s390/tpf.h" + tm_file="s390/s390x.h s390/s390.h elfos.h glibc-stdint.h s390/tpf.h" tm_p_file=s390/s390-protos.h c_target_objs="${c_target_objs} s390-c.o" cxx_target_objs="${cxx_target_objs} s390-c.o" @@ -3233,7 +3150,7 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ case ${with_endian} in little*) tm_file="sh/little.h ${tm_file}" ;; esac - tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h" + tm_file="${tm_file} elfos.h sh/elf.h" case ${target} in sh*-*-linux*) tmake_file="${tmake_file} sh/t-linux" if test x$enable_fdpic = xyes; then @@ -3354,14 +3271,14 @@ sh-*-elf* | sh[12346l]*-*-elf* | \ ;; sh-*-rtems*) tmake_file="${tmake_file} sh/t-sh sh/t-rtems" - tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h newlib-stdint.h" + tm_file="${tm_file} elfos.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h newlib-stdint.h" ;; sh-wrs-vxworks) tmake_file="$tmake_file sh/t-sh sh/t-vxworks" tm_file="${tm_file} elfos.h sh/elf.h sh/embed-elf.h vx-common.h vxworks.h sh/vxworks.h" ;; sparc-*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp-elf.h" + tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp-elf.h" case ${target} in *-leon-*) tmake_file="sparc/t-sparc sparc/t-leon" @@ -3375,11 +3292,11 @@ sparc-*-elf*) esac ;; sparc-*-rtems*) - tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h" + tm_file="${tm_file} elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h" tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems" ;; sparc-*-linux*) - tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h" + tm_file="${tm_file} elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h" extra_options="${extra_options} sparc/long-double-switch.opt" case ${target} in *-leon-*) @@ -3401,7 +3318,7 @@ sparc-*-linux*) fi ;; sparc-*-netbsdelf*) - tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h" + tm_file="${tm_file} elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" extra_options="${extra_options} sparc/long-double-switch.opt" tmake_file="${tmake_file} sparc/t-sparc" @@ -3423,22 +3340,22 @@ sparc-wrs-vxworks) tmake_file="${tmake_file} sparc/t-sparc sparc/t-vxworks" ;; sparc64-*-elf*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h" + tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h" extra_options="${extra_options}" tmake_file="${tmake_file} sparc/t-sparc" ;; sparc64-*-rtems*) - tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h" + tm_file="${tm_file} elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h" extra_options="${extra_options}" tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems-64" ;; sparc64-*-linux*) - tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default64.h sparc/linux64.h sparc/tso.h" + tm_file="sparc/biarch64.h ${tm_file} elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default64.h sparc/linux64.h sparc/tso.h" extra_options="${extra_options} sparc/long-double-switch.opt" tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux64" ;; sparc64-*-freebsd*|ultrasparc-*-freebsd*) - tm_file="${tm_file} ${fbsd_tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/freebsd.h" + tm_file="${tm_file} ${fbsd_tm_file} elfos.h sparc/sysv4.h sparc/freebsd.h" extra_options="${extra_options} sparc/long-double-switch.opt" case "x$with_cpu" in xultrasparc) ;; @@ -3449,13 +3366,13 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*) ;; sparc64-*-netbsd*) tm_file="sparc/biarch64.h ${tm_file}" - tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h" + tm_file="${tm_file} elfos.h sparc/sysv4.h ${nbsd_tm_file} sparc/netbsd-elf.h" extra_options="${extra_options} netbsd.opt netbsd-elf.opt" extra_options="${extra_options} sparc/long-double-switch.opt" tmake_file="${tmake_file} sparc/t-sparc sparc/t-netbsd64" ;; sparc64-*-openbsd*) - tm_file="sparc/openbsd1-64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp64-elf.h" + tm_file="sparc/openbsd1-64.h ${tm_file} elfos.h sparc/sysv4.h sparc/sp64-elf.h" tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h sparc/openbsd64.h" extra_options="${extra_options} openbsd.opt" extra_options="${extra_options}" @@ -3465,13 +3382,13 @@ sparc64-*-openbsd*) ;; tic6x-*-elf) tm_file="elfos.h ${tm_file} c6x/elf-common.h c6x/elf.h" - tm_file="${tm_file} dbxelf.h tm-dwarf2.h newlib-stdint.h" + tm_file="${tm_file} tm-dwarf2.h newlib-stdint.h" tmake_file="c6x/t-c6x c6x/t-c6x-elf" use_collect2=no ;; tic6x-*-uclinux) tm_file="elfos.h ${tm_file} gnu-user.h linux.h c6x/elf-common.h c6x/uclinux-elf.h" - tm_file="${tm_file} dbxelf.h tm-dwarf2.h glibc-stdint.h" + tm_file="${tm_file} tm-dwarf2.h glibc-stdint.h" tm_file="${tm_file} ./sysroot-suffix.h" tmake_file="t-sysroot-suffix t-slibgcc" tmake_file="${tmake_file} c6x/t-c6x c6x/t-c6x-elf c6x/t-c6x-uclinux" @@ -3515,7 +3432,7 @@ v850*-*-*) use_gcc_stdint=wrap ;; vax-*-linux*) - tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h vax/elf.h vax/linux.h" + tm_file="${tm_file} elfos.h gnu-user.h linux.h vax/elf.h vax/linux.h" extra_options="${extra_options} vax/elf.opt" ;; vax-*-netbsdelf*) @@ -3524,14 +3441,13 @@ vax-*-netbsdelf*) tm_defines="${tm_defines} CHAR_FAST8=1 SHORT_FAST16=1" ;; visium-*-elf*) - tm_file="dbxelf.h elfos.h ${tm_file} visium/elf.h newlib-stdint.h" + tm_file="elfos.h ${tm_file} visium/elf.h newlib-stdint.h" tmake_file="visium/t-visium visium/t-crtstuff" ;; xstormy16-*-elf) # For historical reasons, the target files omit the 'x'. - tm_file="dbxelf.h elfos.h newlib-stdint.h stormy16/stormy16.h" + tm_file="elfos.h newlib-stdint.h stormy16/stormy16.h" tm_p_file=stormy16/stormy16-protos.h - tm_d_file="elfos.h stormy16/stormy16.h" md_file=stormy16/stormy16.md out_file=stormy16/stormy16.cc extra_options=stormy16/stormy16.opt @@ -3555,11 +3471,6 @@ am33_2.0-*-linux*) gas=yes gnu_ld=yes use_collect2=no ;; -m32c-*-rtems*) - tm_file="elfos.h ${tm_file} m32c/rtems.h rtems.h newlib-stdint.h" - c_target_objs="m32c-pragma.o" - cxx_target_objs="m32c-pragma.o" - ;; m32c-*-elf*) tm_file="elfos.h newlib-stdint.h ${tm_file}" c_target_objs="m32c-pragma.o" diff --git a/gcc/config.host b/gcc/config.host index 4ca300f..992638d 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -201,11 +201,6 @@ esac # Machine-specific settings. case ${host} in - hppa1.0-*-hpux10* | hppa1.1-*-hpux10* | hppa2*-*-hpux10*) - out_host_hook_obj=host-hpux.o - host_xmake_file="${host_xmake_file} x-hpux" - ;; - hppa1.0-*-hpux11* | hppa1.1-*-hpux11* | hppa2*-*-hpux11* | \ hppa*64*-*-hpux11*) out_host_hook_obj=host-hpux.o host_xmake_file="${host_xmake_file} x-hpux" diff --git a/gcc/config.in b/gcc/config.in index abab9bf..9c53319 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -452,12 +452,6 @@ #endif -/* Define if your assembler supports the --gstabs option. */ -#ifndef USED_FOR_TARGET -#undef HAVE_AS_GSTABS_DEBUG_FLAG -#endif - - /* Define if your assembler supports the Sun syntax for cmov. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_IX86_CMOV_SUN_SYNTAX @@ -746,12 +740,6 @@ #endif -/* Define if your assembler supports .stabs. */ -#ifndef USED_FOR_TARGET -#undef HAVE_AS_STABS_DIRECTIVE -#endif - - /* Define if your assembler and linker support thread-local storage. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_TLS @@ -2111,13 +2099,6 @@ #endif -/* Define if your assembler supports AIX debug frame section label reference. - */ -#ifndef USED_FOR_TARGET -#undef HAVE_XCOFF_DWARF_EXTRAS -#endif - - /* Define if you have a working <zstd.h> header file. */ #ifndef USED_FOR_TARGET #undef HAVE_ZSTD_H diff --git a/gcc/config/aarch64/aarch64-d.cc b/gcc/config/aarch64/aarch64-d.cc index d3fcc0b..e0e0401 100644 --- a/gcc/config/aarch64/aarch64-d.cc +++ b/gcc/config/aarch64/aarch64-d.cc @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/aarch64/aarch64-d.h b/gcc/config/aarch64/aarch64-d.h new file mode 100644 index 0000000..c605a68 --- /dev/null +++ b/gcc/config/aarch64/aarch64-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the AArch64 architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Defined in aarch64-d.cc */ +extern void aarch64_d_target_versions (void); +extern void aarch64_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS aarch64_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO aarch64_d_register_target_info diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h index 410a40b..8e05b1f 100644 --- a/gcc/config/aarch64/aarch64-elf.h +++ b/gcc/config/aarch64/aarch64-elf.h @@ -144,7 +144,4 @@ ASM_MABI_SPEC #undef TYPE_OPERAND_FMT #define TYPE_OPERAND_FMT "%%%s" -/* Stabs debug not required. */ -#undef DBX_DEBUGGING_INFO - #endif /* GCC_AARCH64_ELF_H */ diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 19c9d3c..99af10a 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -878,7 +878,7 @@ rtx aarch64_simd_vect_par_cnst_half (machine_mode, int, bool); rtx aarch64_gen_stepped_int_parallel (unsigned int, int, int); bool aarch64_stepped_int_parallel_p (rtx, int); rtx aarch64_tls_get_addr (void); -unsigned aarch64_dbx_register_number (unsigned); +unsigned aarch64_debugger_regno (unsigned); unsigned aarch64_trampoline_size (void); void aarch64_asm_output_labelref (FILE *, const char *); void aarch64_cpu_cpp_builtins (cpp_reader *); @@ -1040,10 +1040,6 @@ enum aarch64_parse_opt_result aarch64_parse_extension (const char *, void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates); std::string aarch64_get_extension_string_for_isa_flags (uint64_t, uint64_t); -/* Defined in aarch64-d.cc */ -extern void aarch64_d_target_versions (void); -extern void aarch64_d_register_target_info (void); - rtl_opt_pass *make_pass_fma_steering (gcc::context *); rtl_opt_pass *make_pass_track_speculation (gcc::context *); rtl_opt_pass *make_pass_tag_collision_avoidance (gcc::context *); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 4b486ae..b12f13f 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -3357,7 +3357,7 @@ aarch64_reassociation_width (unsigned opc, machine_mode mode) /* Provide a mapping from gcc register numbers to dwarf register numbers. */ unsigned -aarch64_dbx_register_number (unsigned regno) +aarch64_debugger_regno (unsigned regno) { if (GP_REGNUM_P (regno)) return AARCH64_DWARF_R0 + regno - R0_REGNUM; @@ -16671,7 +16671,8 @@ aarch64_vector_costs::prefer_unrolled_loop () const if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "Number of insns in" - " unrolled Advanced SIMD loop = %d\n", + " unrolled Advanced SIMD loop = " + HOST_WIDE_INT_PRINT_UNSIGNED "\n", m_unrolled_advsimd_stmts); /* The balance here is tricky. On the one hand, we can't be sure whether diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 80cfe4b..2eed6e8 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -26,10 +26,6 @@ #define TARGET_CPU_CPP_BUILTINS() \ aarch64_cpu_cpp_builtins (pfile) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS aarch64_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO aarch64_d_register_target_info - #define REGISTER_TARGET_PRAGMAS() aarch64_register_pragmas () @@ -631,12 +627,12 @@ #define DWARF_FRAME_REGISTERS (DWARF_ALT_FRAME_RETURN_COLUMN + 1) -#define DBX_REGISTER_NUMBER(REGNO) aarch64_dbx_register_number (REGNO) +#define DEBUGGER_REGNO(REGNO) aarch64_debugger_regno (REGNO) /* Provide a definition of DWARF_FRAME_REGNUM here so that fallback unwinders can use DWARF_ALT_FRAME_RETURN_COLUMN defined below. This is just the same as the default definition in dwarf2out.cc. */ #undef DWARF_FRAME_REGNUM -#define DWARF_FRAME_REGNUM(REGNO) DBX_REGISTER_NUMBER (REGNO) +#define DWARF_FRAME_REGNUM(REGNO) DEBUGGER_REGNO (REGNO) #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LR_REGNUM) diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc index 0a85e66..66c1714 100644 --- a/gcc/config/alpha/alpha.cc +++ b/gcc/config/alpha/alpha.cc @@ -8458,10 +8458,6 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, } #endif /* TARGET_ABI_OSF */ -/* Debugging support. */ - -#include "gstab.h" - /* Name of the file containing the current function. */ static const char *current_function_file = ""; diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index c01353a..1f6d2ca 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -638,7 +638,7 @@ enum reg_class { can use DWARF_ALT_FRAME_RETURN_COLUMN defined below. This is just the same as the default definition in dwarf2out.cc. */ #undef DWARF_FRAME_REGNUM -#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) +#define DWARF_FRAME_REGNUM(REG) DEBUGGER_REGNO (REG) /* Before the prologue, RA lives in $26. */ #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26) diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h index 4447a7f..c9cd42e 100644 --- a/gcc/config/alpha/elf.h +++ b/gcc/config/alpha/elf.h @@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see #define CC1_SPEC "%{G*}" #undef ASM_SPEC -#define ASM_SPEC "%{G*} %{relax:-relax} %{!gstabs*:-no-mdebug}%{gstabs*:-mdebug} %{mcpu=*:-m%*}" +#define ASM_SPEC "%{G*} %{relax:-relax} %{mcpu=*:-m%*}" /* Do not output a .file directive at the beginning of the input file. */ diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index 064790b..db4b56b 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -1885,7 +1885,7 @@ arc_init_reg_tables (void) Because mlo / mhi form a 64 bit value, we use different gcc internal register numbers to make them form a register pair as the gcc internals know it. mmid gets number 57, if still available, and mlo / mhi get - number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER + number 58 and 59, depending on endianness. We use DEBUGGER_REGNO to map this back. */ char rname56[5] = "r56"; char rname57[5] = "r57"; diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 539a166..0280b53 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -1330,12 +1330,7 @@ do { \ /* Debugging information. */ -/* Generate DBX and DWARF debugging information. */ -#ifdef DBX_DEBUGGING_INFO -#undef DBX_DEBUGGING_INFO -#endif -#define DBX_DEBUGGING_INFO - +/* Generate DWARF debugging information. */ #ifdef DWARF2_DEBUGGING_INFO #undef DWARF2_DEBUGGING_INFO #endif @@ -1345,8 +1340,8 @@ do { \ #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -/* How to renumber registers for dbx and gdb. */ -#define DBX_REGISTER_NUMBER(REGNO) \ +/* How to renumber registers for gdb. */ +#define DEBUGGER_REGNO(REGNO) \ ((TARGET_MULMAC_32BY16_SET && (REGNO) >= 56 && (REGNO) <= 57) \ ? ((REGNO) ^ !TARGET_BIG_ENDIAN) \ : (TARGET_MUL64_SET && (REGNO) >= 57 && (REGNO) <= 58) \ @@ -1385,9 +1380,6 @@ do { \ #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 2) -/* Turn off splitting of long stabs. */ -#define DBX_CONTIN_LENGTH 0 - /* Miscellaneous. */ /* Specify the machine mode that this machine uses diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h index b918ad3..cfb8db5 100644 --- a/gcc/config/arm/aout.h +++ b/gcc/config/arm/aout.h @@ -145,15 +145,6 @@ #define NO_DOLLAR_IN_LABEL 1 #endif -/* Generate DBX debugging information. riscix.h will undefine this because - the native assembler does not support stabs. */ -#define DBX_DEBUGGING_INFO 1 - -/* Acorn dbx moans about continuation chars, so don't use any. */ -#ifndef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 0 -#endif - /* Output a function label definition. */ #ifndef ASM_DECLARE_FUNCTION_NAME #define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \ diff --git a/gcc/config/arm/arm-d.cc b/gcc/config/arm/arm-d.cc index d65b752..5c89f1b 100644 --- a/gcc/config/arm/arm-d.cc +++ b/gcc/config/arm/arm-d.cc @@ -21,9 +21,10 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" +#include "arm-protos.h" /* Implement TARGET_D_CPU_VERSIONS for ARM targets. */ diff --git a/gcc/config/arm/arm-d.h b/gcc/config/arm/arm-d.h new file mode 100644 index 0000000..479a89b --- /dev/null +++ b/gcc/config/arm/arm-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the ARM architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Defined in arm-d.cc */ +extern void arm_d_target_versions (void); +extern void arm_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS arm_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO arm_d_register_target_info diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index f8aabbd..550272f 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -45,7 +45,7 @@ extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int, unsigned int); extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int, unsigned int); -extern unsigned int arm_dbx_register_number (unsigned int); +extern unsigned int arm_debugger_regno (unsigned int); extern void arm_output_fn_unwind (FILE *, bool); extern rtx arm_expand_builtin (tree exp, rtx target, rtx subtarget @@ -402,10 +402,6 @@ extern void arm_lang_object_attributes_init (void); extern void arm_register_target_pragmas (void); extern void arm_cpu_cpp_builtins (struct cpp_reader *); -/* Defined in arm-d.cc */ -extern void arm_d_target_versions (void); -extern void arm_d_register_target_info (void); - extern bool arm_is_constant_pool_ref (rtx); /* The bits in this mask specify which instruction scheduling options should diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index eca99c9..1a37536 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -29568,7 +29568,7 @@ arm_shift_truncation_mask (machine_mode mode) /* Map internal gcc register numbers to DWARF2 register numbers. */ unsigned int -arm_dbx_register_number (unsigned int regno) +arm_debugger_regno (unsigned int regno) { if (regno < 16) return regno; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index f479540..984ab78 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -47,10 +47,6 @@ extern char arm_arch_name[]; /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() arm_cpu_cpp_builtins (pfile) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS arm_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO arm_d_register_target_info - #include "config/arm/arm-opts.h" /* The processor for which instructions should be scheduled. */ @@ -1062,7 +1058,7 @@ extern const int arm_arch_cde_coproc_bits[]; /* VFP (VFP3) adds 32 (64) + 1 VFPCC. */ #define FIRST_PSEUDO_REGISTER 107 -#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO) +#define DEBUGGER_REGNO(REGNO) arm_debugger_regno (REGNO) /* Value should be nonzero if functions must have frame pointers. Zero means the frame pointer need not be set up (and parms may be accessed diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h index d239c73..ef1bba2 100644 --- a/gcc/config/arm/netbsd-elf.h +++ b/gcc/config/arm/netbsd-elf.h @@ -85,9 +85,6 @@ #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "long int" -/* We don't have any limit on the length as out debugger is GDB. */ -#undef DBX_CONTIN_LENGTH - /* NetBSD does its profiling differently to the Acorn compiler. We don't need a word following the mcount call; and to skip it requires either an assembly stub or use of fomit-frame-pointer when diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index a442a81..4e77530 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -1094,8 +1094,8 @@ extern rtx bfin_cc_rtx, bfin_rets_rtx; /* This works for GAS and some other assemblers. */ #define SET_ASM_OP ".set " -/* DBX register number for a given compiler register number */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +/* Debugger register number for a given compiler register number */ +#define DEBUGGER_REGNO(REGNO) (REGNO) #define SIZE_ASM_OP "\t.size\t" diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc index 6a0e3bb..9cb56cf 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -291,6 +291,7 @@ void bpf_target_macros (cpp_reader *pfile) { builtin_define ("__BPF__"); + builtin_define ("__bpf__"); if (TARGET_BIG_ENDIAN) builtin_define ("__BPF_BIG_ENDIAN__"); @@ -659,12 +660,15 @@ bpf_address_base_p (rtx x, bool strict) target machine for a memory operand of mode MODE. */ static bool -bpf_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, +bpf_legitimate_address_p (machine_mode mode, rtx x, bool strict) { switch (GET_CODE (x)) { + case CONST_INT: + return (mode == FUNCTION_MODE); + case REG: return bpf_address_base_p (x, strict); @@ -1311,6 +1315,22 @@ bpf_core_walk (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } +/* Implement target hook small_register_classes_for_mode_p. */ + +static bool +bpf_small_register_classes_for_mode_p (machine_mode mode) +{ + if (TARGET_XBPF) + return 1; + else + /* Avoid putting function addresses in registers, as calling these + is not supported in eBPF. */ + return (mode != FUNCTION_MODE); +} + +#undef TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P +#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \ + bpf_small_register_classes_for_mode_p /* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN (see gccint manual section Target Macros::Misc.). diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc index cceaaa9..8897a04 100644 --- a/gcc/config/bpf/coreout.cc +++ b/gcc/config/bpf/coreout.cc @@ -207,7 +207,6 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, const tree node) if (TREE_CODE (node) == FIELD_DECL) { const tree container = DECL_CONTEXT (node); - const char * name = IDENTIFIER_POINTER (DECL_NAME (node)); /* Lookup the CTF type info for the containing type. */ dw_die_ref die = lookup_type_die (container); @@ -222,16 +221,21 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, const tree node) if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return -1; + tree field = TYPE_FIELDS (container); int i = 0; ctf_dmdef_t * dmd; for (dmd = dtd->dtd_u.dtu_members; dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd)) { - if (get_btf_id (dmd->dmd_type) > BTF_MAX_TYPE) - continue; - if (strcmp (dmd->dmd_name, name) == 0) - return i; - i++; + bool field_has_btf = get_btf_id (dmd->dmd_type) <= BTF_MAX_TYPE; + + if (field == node) + return field_has_btf ? i : -1; + + if (field_has_btf) + i++; + + field = DECL_CHAIN (field); } } return -1; diff --git a/gcc/config/c6x/c6x.cc b/gcc/config/c6x/c6x.cc index dc01a6e..4baf302 100644 --- a/gcc/config/c6x/c6x.cc +++ b/gcc/config/c6x/c6x.cc @@ -195,7 +195,7 @@ typedef int unit_req_table[2][UNIT_REQ_MAX]; static unit_req_table unit_reqs; /* Register map for debugging. */ -unsigned const dbx_register_map[FIRST_PSEUDO_REGISTER] = +unsigned const debugger_register_map[FIRST_PSEUDO_REGISTER] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* A0 - A15. */ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, /* A16 - A32. */ diff --git a/gcc/config/c6x/c6x.h b/gcc/config/c6x/c6x.h index 766ce1e..88fc73d 100644 --- a/gcc/config/c6x/c6x.h +++ b/gcc/config/c6x/c6x.h @@ -503,9 +503,9 @@ struct GTY(()) machine_function "B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31", \ "FP", "ARGP", "ILC" } -#define DBX_REGISTER_NUMBER(N) (dbx_register_map[(N)]) +#define DEBUGGER_REGNO(N) (debugger_register_map[(N)]) -extern unsigned const dbx_register_map[FIRST_PSEUDO_REGISTER]; +extern unsigned const debugger_register_map[FIRST_PSEUDO_REGISTER]; #define FINAL_PRESCAN_INSN c6x_final_prescan_insn diff --git a/gcc/config/cr16/constraints.md b/gcc/config/cr16/constraints.md deleted file mode 100644 index 708fe21..0000000 --- a/gcc/config/cr16/constraints.md +++ /dev/null @@ -1,81 +0,0 @@ -;; Predicates of machine description for CR16. -;; Copyright (C) 2012-2022 Free Software Foundation, Inc. -;; Contributed by KPIT Cummins Infosystems Limited. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published -;; by the Free Software Foundation; either version 3, or (at your -;; option) any later version. -;; -;; GCC is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Constraints -;; Register constraints -(define_register_constraint "b" "NOSP_REGS" - "@no sp registers") - -(define_register_constraint "c" "SHORT_REGS" - "@short registers") - -(define_register_constraint "d" "LONG_REGS" - "@long registers") - -;; Integer constraints. -(define_constraint "I" - "A signed 4-bit immediate." - (and (match_code "const_int") - (match_test "SIGNED_INT_FITS_N_BITS (ival, 4)"))) - -(define_constraint "J" - "A signed 5-bit immediate." - (and (match_code "const_int") - (match_test "SIGNED_INT_FITS_N_BITS (ival, 5)"))) - -(define_constraint "K" - "A signed 6-bit immediate." - (and (match_code "const_int") - (match_test "SIGNED_INT_FITS_N_BITS (ival, 6)"))) - -(define_constraint "L" - "A unsigned 4-bit immediate." - (and (match_code "const_int") - (match_test "UNSIGNED_INT_FITS_N_BITS (ival, 4)"))) - -(define_constraint "M" - "A unsigned and customized 4-bit immediate." - (and (match_code "const_int") - (match_test "(IN_RANGE_P (ival, 0, 15) && ((ival != 9) && (ival != 11)))"))) - -(define_constraint "N" - "A signed 16-bit immediate." - (and (match_code "const_int") - (match_test "IN_RANGE_P (ival, -32768, 32767)"))) - -(define_constraint "O" - "A unsigned 20-bit immediate." - (and (match_code "const_int") - (match_test "IN_RANGE_P (ival, 0, 1048575)"))) - -(define_constraint "Q" - "A shift QI immediate." - (and (match_code "const_int") - (match_test "IN_RANGE_P (ival, 0, 7)"))) - -(define_constraint "R" - "A shift HI immediate." - (and (match_code "const_int") - (match_test "IN_RANGE_P (ival, 0, 15)"))) - -(define_constraint "S" - "A shift SI immediate." - (and (match_code "const_int") - (match_test "IN_RANGE_P (ival, 0, 31)"))) diff --git a/gcc/config/cr16/cr16-protos.h b/gcc/config/cr16/cr16-protos.h deleted file mode 100644 index 300bb31..0000000 --- a/gcc/config/cr16/cr16-protos.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Prototypes for exported functions defined in cr16.cc - Copyright (C) 2012-2022 Free Software Foundation, Inc. - Contributed by KPIT Cummins Infosystems Limited. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef GCC_CR16_PROTOS_H -#define GCC_CR16_PROTOS_H - -/* Register usage. */ -extern enum reg_class cr16_regno_reg_class (int); - -/* Passing function arguments. */ -extern int cr16_function_arg_regno_p (int); - -#ifdef TREE_CODE -#ifdef RTX_CODE - -extern void cr16_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx); - -#endif /* RTX_CODE. */ -#endif /* TREE_CODE. */ - -/* Enumeration giving the various data models we support. */ -enum data_model_type -{ - DM_DEFAULT, /* Default data model (in CR16C/C+ - up to 16M). */ - DM_NEAR, /* Near data model (in CR16C/C+ - up to 1M). */ - DM_FAR, /* Far data model (in CR16C+ - up to 4G) - (in CR16C - up to 16M). */ - ILLEGAL_DM /* Illegal data model. */ -}; - -#ifdef RTX_CODE - -/* Addressing Modes. */ -struct cr16_address -{ - rtx base; /* Base register: Any register or register pair. */ - rtx index; /* Index register: If one is present. */ - rtx disp; /* Displacement or Absolute address. */ - enum data_model_type data; /* data ref type. */ - int code; /* Whether the address is code address. - 0 - data, 1 - code label, 2 - function label. */ -}; - -enum cr16_addrtype -{ - CR16_INVALID, - CR16_REG_REL, - CR16_REGP_REL, - CR16_INDEX_REGP_REL, - CR16_ABSOLUTE -}; - -extern int cr16_operand_bit_pos (int val, int bitval); -extern void cr16_decompose_const (rtx x, int *code, - enum data_model_type *data, - bool treat_as_const); -extern enum cr16_addrtype cr16_decompose_address (rtx addr, - struct cr16_address *out, - bool debug_print, - bool treat_as_const); -extern int cr16_const_double_ok (rtx op); -extern int legitimate_pic_operand_p (rtx); -extern rtx legitimize_pic_address (rtx, machine_mode, rtx); - - -/* Prologue/Epilogue functions. */ -extern int cr16_initial_elimination_offset (int, int); -extern char *cr16_prepare_push_pop_string (int); -extern void cr16_expand_prologue (void); -extern void cr16_expand_epilogue (void); -extern const char *cr16_emit_add_sub_di (rtx *, enum rtx_code); -extern const char *cr16_emit_logical_di (rtx *, enum rtx_code); - -#endif /* RTX_CODE. */ - -/* Handling the "interrupt" attribute. */ -extern int cr16_interrupt_function_p (void); -extern bool cr16_is_data_model (enum data_model_type); -extern poly_int64 cr16_push_rounding (poly_int64); - -#endif /* Not GCC_CR16_PROTOS_H. */ diff --git a/gcc/config/cr16/cr16.cc b/gcc/config/cr16/cr16.cc deleted file mode 100644 index 55dad99..0000000 --- a/gcc/config/cr16/cr16.cc +++ /dev/null @@ -1,2201 +0,0 @@ -/* Output routines for CR16 processor. - Copyright (C) 2012-2022 Free Software Foundation, Inc. - Contributed by KPIT Cummins Infosystems Limited. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#define IN_TARGET_CODE 1 - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "target.h" -#include "rtl.h" -#include "tree.h" -#include "stringpool.h" -#include "attribs.h" -#include "df.h" -#include "memmodel.h" -#include "tm_p.h" -#include "regs.h" -#include "emit-rtl.h" -#include "diagnostic-core.h" -#include "stor-layout.h" -#include "calls.h" -#include "conditions.h" -#include "output.h" -#include "expr.h" -#include "builtins.h" - -/* This file should be included last. */ -#include "target-def.h" - -/* Definitions. */ - -/* Maximum number of register used for passing parameters. */ -#define MAX_REG_FOR_PASSING_ARGS 6 - -/* Minimum number register used for passing parameters. */ -#define MIN_REG_FOR_PASSING_ARGS 2 - -/* The maximum count of words supported in the assembly of the architecture in - a push/pop instruction. */ -#define MAX_COUNT 8 - -/* Predicate is true if the current function is a 'noreturn' function, - i.e. it is qualified as volatile. */ -#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl)) - -/* Predicate that holds when we need to save registers even for 'noreturn' - functions, to accommodate for unwinding. */ -#define MUST_SAVE_REGS_P() \ - (flag_unwind_tables || (flag_exceptions && !UI_SJLJ)) - -/* Nonzero if the rtx X is a signed const int of n bits. */ -#define RTX_SIGNED_INT_FITS_N_BITS(X, n) \ - ((GET_CODE (X) == CONST_INT \ - && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0) - -/* Nonzero if the rtx X is an unsigned const int of n bits. */ -#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \ - ((GET_CODE (X) == CONST_INT \ - && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0) - -/* Structure for stack computations. */ - -/* variable definitions in the struture - args_size Number of bytes saved on the stack for local - variables - - reg_size Number of bytes saved on the stack for - non-scratch registers - - total_size The sum of 2 sizes: locals vars and padding byte - for saving the registers. Used in expand_prologue() - and expand_epilogue() - - last_reg_to_save Will hold the number of the last register the - prologue saves, -1 if no register is saved - - save_regs[16] Each object in the array is a register number. - Mark 1 for registers that need to be saved - - num_regs Number of registers saved - - initialized Non-zero if frame size already calculated, not - used yet - - function_makes_calls Does the function make calls ? not used yet. */ - -struct cr16_frame_info -{ - unsigned long var_size; - unsigned long args_size; - unsigned int reg_size; - unsigned long total_size; - long last_reg_to_save; - long save_regs[FIRST_PSEUDO_REGISTER]; - int num_regs; - int initialized; - int function_makes_calls; -}; - -/* Current frame information calculated by cr16_compute_frame_size. */ -static struct cr16_frame_info current_frame_info; - -/* Static Variables. */ - -/* Data model that was supplied by user via command line option - This will be overridden in case of invalid combination - of core and data model options are supplied. */ -static enum data_model_type data_model = DM_DEFAULT; - -/* TARGETM Function Prototypes and forward declarations */ -static void cr16_print_operand (FILE *, rtx, int); -static void cr16_print_operand_address (FILE *, machine_mode, rtx); - -/* Stack layout and calling conventions. */ -#undef TARGET_STRUCT_VALUE_RTX -#define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx -#undef TARGET_RETURN_IN_MEMORY -#define TARGET_RETURN_IN_MEMORY cr16_return_in_memory - -/* Target-specific uses of '__attribute__'. */ -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE cr16_attribute_table -#undef TARGET_NARROW_VOLATILE_BITFIELD -#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false - -/* EH related. */ -#undef TARGET_UNWIND_WORD_MODE -#define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode - -/* Override Options. */ -#undef TARGET_OPTION_OVERRIDE -#define TARGET_OPTION_OVERRIDE cr16_override_options - -/* Conditional register usuage. */ -#undef TARGET_CONDITIONAL_REGISTER_USAGE -#define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage - -/* Controlling register spills. */ -#undef TARGET_CLASS_LIKELY_SPILLED_P -#define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p - -/* Passing function arguments. */ -#undef TARGET_PUSH_ARGUMENT -#define TARGET_PUSH_ARGUMENT hook_bool_uint_true -#undef TARGET_FUNCTION_ARG -#define TARGET_FUNCTION_ARG cr16_function_arg -#undef TARGET_FUNCTION_ARG_ADVANCE -#define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance -#undef TARGET_RETURN_POPS_ARGS -#define TARGET_RETURN_POPS_ARGS cr16_return_pops_args - -/* Initialize the GCC target structure. */ -#undef TARGET_FRAME_POINTER_REQUIRED -#define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required -#undef TARGET_CAN_ELIMINATE -#define TARGET_CAN_ELIMINATE cr16_can_eliminate -#undef TARGET_LEGITIMIZE_ADDRESS -#define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address -#undef TARGET_LEGITIMATE_CONSTANT_P -#define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p -#undef TARGET_LEGITIMATE_ADDRESS_P -#define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p - -#undef TARGET_LRA_P -#define TARGET_LRA_P hook_bool_void_false - -/* Returning function value. */ -#undef TARGET_FUNCTION_VALUE -#define TARGET_FUNCTION_VALUE cr16_function_value -#undef TARGET_LIBCALL_VALUE -#define TARGET_LIBCALL_VALUE cr16_libcall_value -#undef TARGET_FUNCTION_VALUE_REGNO_P -#define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p - -/* printing the values. */ -#undef TARGET_PRINT_OPERAND -#define TARGET_PRINT_OPERAND cr16_print_operand -#undef TARGET_PRINT_OPERAND_ADDRESS -#define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address - -/* Relative costs of operations. */ -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST cr16_address_cost -#undef TARGET_REGISTER_MOVE_COST -#define TARGET_REGISTER_MOVE_COST cr16_register_move_cost -#undef TARGET_MEMORY_MOVE_COST -#define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost - -#undef TARGET_CONSTANT_ALIGNMENT -#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings - -/* Table of machine attributes. */ -static const struct attribute_spec cr16_attribute_table[] = { - /* ISRs have special prologue and epilogue requirements. */ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, - affects_type_identity, handler, exclude }. */ - {"interrupt", 0, 0, false, true, true, false, NULL, NULL}, - {NULL, 0, 0, false, false, false, false, NULL, NULL} -}; - -/* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive - .?byte directive along with @c is not understood by assembler. - Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same - as TARGET_ASM_ALIGNED_xx_OP. */ -#undef TARGET_ASM_UNALIGNED_HI_OP -#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP -#undef TARGET_ASM_UNALIGNED_SI_OP -#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP -#undef TARGET_ASM_UNALIGNED_DI_OP -#define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP - -#undef TARGET_HARD_REGNO_NREGS -#define TARGET_HARD_REGNO_NREGS cr16_hard_regno_nregs -#undef TARGET_HARD_REGNO_MODE_OK -#define TARGET_HARD_REGNO_MODE_OK cr16_hard_regno_mode_ok -#undef TARGET_MODES_TIEABLE_P -#define TARGET_MODES_TIEABLE_P cr16_modes_tieable_p - -/* Target hook implementations. */ - -/* Implements hook TARGET_RETURN_IN_MEMORY. */ -static bool -cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) -{ - const HOST_WIDE_INT size = int_size_in_bytes (type); - return ((size == -1) || (size > 8)); -} - -/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ -static bool -cr16_class_likely_spilled_p (reg_class_t rclass) -{ - if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS - || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS) - return true; - - return false; -} - -static poly_int64 -cr16_return_pops_args (tree, tree, poly_int64) -{ - return 0; -} - -/* Returns true if data model selected via command line option - is same as function argument. */ -bool -cr16_is_data_model (enum data_model_type model) -{ - return (model == data_model); -} - -/* Parse relevant options and override. */ -static void -cr16_override_options (void) -{ - /* Disable -fdelete-null-pointer-checks option for CR16 target. - Programs which rely on NULL pointer dereferences _not_ halting the - program may not work properly with this option. So disable this - option. */ - flag_delete_null_pointer_checks = 0; - - /* FIXME: To avoid spill_failure ICE during exception handling, - * disable cse_fllow_jumps. The spill error occurs when compiler - * can't find a suitable candidate in GENERAL_REGS class to reload - * a 32bit register. - * Need to find a better way of avoiding this situation. */ - if (flag_exceptions) - flag_cse_follow_jumps = 0; - - /* If -fpic option, data_model == DM_FAR. */ - if (flag_pic == NEAR_PIC) - { - data_model = DM_FAR; - } - - /* The only option we want to examine is data model option. */ - if (cr16_data_model) - { - if (strcmp (cr16_data_model, "medium") == 0) - data_model = DM_DEFAULT; - else if (strcmp (cr16_data_model, "near") == 0) - data_model = DM_NEAR; - else if (strcmp (cr16_data_model, "far") == 0) - { - if (TARGET_CR16CP) - data_model = DM_FAR; - else - error ("data-model=far not valid for cr16c architecture"); - } - else - error ("invalid data model option %<-mdata-model=%s%>", - cr16_data_model); - } - else - data_model = DM_DEFAULT; -} - -/* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */ -static void -cr16_conditional_register_usage (void) -{ - if (flag_pic) - { - fixed_regs[12] = call_used_regs[12] = 1; - } -} - -/* Stack layout and calling conventions routines. */ - -/* Return nonzero if the current function being compiled is an interrupt - function as specified by the "interrupt" attribute. */ -int -cr16_interrupt_function_p (void) -{ - tree attributes; - - attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); - return (lookup_attribute ("interrupt", attributes) != NULL_TREE); -} - -/* Compute values for the array current_frame_info.save_regs and the variable - current_frame_info.reg_size. The index of current_frame_info.save_regs - is numbers of register, each will get 1 if we need to save it in the - current function, 0 if not. current_frame_info.reg_size is the total sum - of the registers being saved. */ -static void -cr16_compute_save_regs (void) -{ - unsigned int regno; - - /* Initialize here so in case the function is no-return it will be -1. */ - current_frame_info.last_reg_to_save = -1; - - /* Initialize the number of bytes to be saved. */ - current_frame_info.reg_size = 0; - - /* No need to save any registers if the function never returns. */ - if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ()) - return; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - { - if (fixed_regs[regno]) - { - current_frame_info.save_regs[regno] = 0; - continue; - } - - /* If this reg is used and not call-used (except RA), save it. */ - if (cr16_interrupt_function_p ()) - { - if (!crtl->is_leaf && call_used_or_fixed_reg_p (regno)) - /* This is a volatile reg in a non-leaf interrupt routine - save - it for the sake of its sons. */ - current_frame_info.save_regs[regno] = 1; - else if (df_regs_ever_live_p (regno)) - /* This reg is used - save it. */ - current_frame_info.save_regs[regno] = 1; - else - /* This reg is not used, and is not a volatile - don't save. */ - current_frame_info.save_regs[regno] = 0; - } - else - { - /* If this reg is used and not call-used (except RA), save it. */ - if (df_regs_ever_live_p (regno) - && (!call_used_or_fixed_reg_p (regno) - || regno == RETURN_ADDRESS_REGNUM)) - current_frame_info.save_regs[regno] = 1; - else - current_frame_info.save_regs[regno] = 0; - } - } - - /* Save registers so the exception handler can modify them. */ - if (crtl->calls_eh_return) - { - unsigned int i; - - for (i = 0;; ++i) - { - regno = EH_RETURN_DATA_REGNO (i); - if (INVALID_REGNUM == regno) - break; - current_frame_info.save_regs[regno] = 1; - } - } - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (current_frame_info.save_regs[regno] == 1) - { - current_frame_info.last_reg_to_save = regno; - if (regno >= CR16_FIRST_DWORD_REGISTER) - current_frame_info.reg_size += CR16_UNITS_PER_DWORD; - else - current_frame_info.reg_size += UNITS_PER_WORD; - } -} - -/* Compute the size of the local area and the size to be adjusted by the - prologue and epilogue. */ -static void -cr16_compute_frame (void) -{ - /* For aligning the local variables. */ - int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT; - int padding_locals; - - /* Padding needed for each element of the frame. */ - current_frame_info.var_size = get_frame_size (); - - /* Align to the stack alignment. */ - padding_locals = current_frame_info.var_size % stack_alignment; - if (padding_locals) - padding_locals = stack_alignment - padding_locals; - - current_frame_info.var_size += padding_locals; - current_frame_info.total_size - = (current_frame_info.var_size - + (ACCUMULATE_OUTGOING_ARGS - ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0)); -} - -/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */ -int -cr16_initial_elimination_offset (int from, int to) -{ - /* Compute this since we need to use current_frame_info.reg_size. */ - cr16_compute_save_regs (); - - /* Compute this since we need to use current_frame_info.var_size. */ - cr16_compute_frame (); - - if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM)) - return (ACCUMULATE_OUTGOING_ARGS - ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0); - else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM)) - return (current_frame_info.reg_size + current_frame_info.var_size); - else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM)) - return (current_frame_info.reg_size + current_frame_info.var_size - + (ACCUMULATE_OUTGOING_ARGS - ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0)); - else - gcc_unreachable (); -} - -/* Register Usage. */ - -/* Return the class number of the smallest class containing reg number REGNO. - This could be a conditional expression or could index an array. */ -enum reg_class -cr16_regno_reg_class (int regno) -{ - if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER)) - return SHORT_REGS; - - if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER)) - return LONG_REGS; - - return NO_REGS; -} - -/* Implement TARGET_HARD_REGNO_NREGS. */ - -static unsigned int -cr16_hard_regno_nregs (unsigned int regno, machine_mode mode) -{ - if (regno >= CR16_FIRST_DWORD_REGISTER) - return CEIL (GET_MODE_SIZE (mode), CR16_UNITS_PER_DWORD); - return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD); -} - -/* Implement TARGET_HARD_REGNO_MODE_OK. On the CR16 architecture, all - registers can hold all modes, except that double precision floats - (and double ints) must fall on even-register boundaries. */ - -static bool -cr16_hard_regno_mode_ok (unsigned int regno, machine_mode mode) -{ - if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11)) - return false; - - if (mode == DImode || mode == DFmode) - { - if ((regno > 8) || (regno & 1)) - return false; - return true; - } - - if ((TARGET_INT32) - && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 ))) - return false; - - /* CC can only hold CCmode values. */ - if (GET_MODE_CLASS (mode) == MODE_CC) - return false; - return true; -} - -/* Implement TARGET_MODES_TIEABLE_P. */ -static bool -cr16_modes_tieable_p (machine_mode mode1, machine_mode mode2) -{ - return GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2); -} - -/* Returns register number for function return value.*/ -static inline unsigned int -cr16_ret_register (void) -{ - return 0; -} - -/* Implements hook TARGET_STRUCT_VALUE_RTX. */ -static rtx -cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED, - int incoming ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (Pmode, cr16_ret_register ()); -} - -/* Returning function value. */ - -/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ -static bool -cr16_function_value_regno_p (const unsigned int regno) -{ - return (regno == cr16_ret_register ()); -} - -/* Create an RTX representing the place where a - library function returns a value of mode MODE. */ -static rtx -cr16_libcall_value (machine_mode mode, - const_rtx func ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (mode, cr16_ret_register ()); -} - -/* Create an RTX representing the place where a - function returns a value of data type VALTYPE. */ -static rtx -cr16_function_value (const_tree type, - const_tree fn_decl_or_type ATTRIBUTE_UNUSED, - bool outgoing ATTRIBUTE_UNUSED) -{ - return gen_rtx_REG (TYPE_MODE (type), cr16_ret_register ()); -} - -/* Passing function arguments. */ - -/* If enough param regs are available for passing the param of type TYPE return - the number of registers needed else 0. */ -static int -enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type, - machine_mode mode) -{ - int type_size; - int remaining_size; - - if (mode != BLKmode) - type_size = GET_MODE_BITSIZE (mode); - else - type_size = int_size_in_bytes (type) * BITS_PER_UNIT; - - remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS - - (MIN_REG_FOR_PASSING_ARGS + cum->ints) + - 1); - - /* Any variable which is too big to pass in two registers, will pass on - stack. */ - if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD)) - return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD; - - return 0; -} - -/* Implement TARGET_FUNCTION_ARG. */ -static rtx -cr16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - cum->last_parm_in_reg = 0; - - /* function_arg () is called with this type just after all the args have - had their registers assigned. The rtx that function_arg returns from - this type is supposed to pass to 'gen_call' but currently it is not - implemented. */ - if (arg.end_marker_p ()) - return NULL_RTX; - - if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0)) - return NULL_RTX; - - if (arg.mode == BLKmode) - { - /* Enable structures that need padding bytes at the end to pass to a - function in registers. */ - if (enough_regs_for_param (cum, arg.type, arg.mode) != 0) - { - cum->last_parm_in_reg = 1; - return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints); - } - } - - if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS) - return NULL_RTX; - else - { - if (enough_regs_for_param (cum, arg.type, arg.mode) != 0) - { - cum->last_parm_in_reg = 1; - return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints); - } - } - - return NULL_RTX; -} - -/* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */ -void -cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, - rtx libfunc ATTRIBUTE_UNUSED) -{ - tree param, next_param; - - cum->ints = 0; - - /* Determine if this function has variable arguments. This is indicated by - the last argument being 'void_type_mode' if there are no variable - arguments. Change here for a different vararg. */ - for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0; - param != NULL_TREE; param = next_param) - { - next_param = TREE_CHAIN (param); - if ((next_param == NULL_TREE) && (TREE_VALUE (param) != void_type_node)) - { - cum->ints = -1; - return; - } - } -} - -/* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */ -static void -cr16_function_arg_advance (cumulative_args_t cum_v, - const function_arg_info &arg) -{ - CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v); - - /* l holds the number of registers required. */ - int l = GET_MODE_BITSIZE (arg.mode) / BITS_PER_WORD; - - /* If the parameter isn't passed on a register don't advance cum. */ - if (!cum->last_parm_in_reg) - return; - - if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0)) - return; - - if ((arg.mode == SImode) || (arg.mode == HImode) - || (arg.mode == QImode) || (arg.mode == DImode)) - { - if (l <= 1) - cum->ints += 1; - else - cum->ints += l; - } - else if ((arg.mode == SFmode) || (arg.mode == DFmode)) - cum->ints += l; - else if (arg.mode == BLKmode) - { - if ((l = enough_regs_for_param (cum, arg.type, arg.mode)) != 0) - cum->ints += l; - } - return; -} - -/* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h. - Return nonzero if N is a register used for passing parameters. */ -int -cr16_function_arg_regno_p (int n) -{ - return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS)); -} - -/* Addressing modes. - Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS - defined in cr16.h. */ - -/* Helper function to check if is a valid base register that can - hold address. */ -static int -cr16_addr_reg_p (rtx addr_reg) -{ - rtx reg; - - if (REG_P (addr_reg)) - reg = addr_reg; - else if ((GET_CODE (addr_reg) == SUBREG) - && REG_P (SUBREG_REG (addr_reg)) - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg))) - <= UNITS_PER_WORD)) - reg = SUBREG_REG (addr_reg); - else - return FALSE; - - if (GET_MODE (reg) != Pmode) - return FALSE; - - return TRUE; -} - -/* Helper functions: Created specifically for decomposing operand of CONST - Recursively look into expression x for code or data symbol. - The function expects the expression to contain combination of - SYMBOL_REF, CONST_INT, (PLUS or MINUS) - LABEL_REF, CONST_INT, (PLUS or MINUS) - SYMBOL_REF - LABEL_REF - All other combinations will result in code = -1 and data = ILLEGAL_DM - code data - -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF - 0 DM_FAR SYMBOL_REF was found and it was far data reference. - 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference. - 1 ILLEGAL_DM LABEL_REF was found. - 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */ -void -cr16_decompose_const (rtx x, int *code, enum data_model_type *data, - bool treat_as_const) -{ - *code = -1; - *data = ILLEGAL_DM; - switch (GET_CODE (x)) - { - case SYMBOL_REF: - *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0; - /* 2 indicates func sym. */ - if (*code == 0) - { - if (CR16_TARGET_DATA_NEAR) - *data = DM_DEFAULT; - else if (CR16_TARGET_DATA_MEDIUM) - *data = DM_FAR; - else if (CR16_TARGET_DATA_FAR) - { - if (treat_as_const) - /* This will be used only for printing - the qualifier. This call is (may be) - made by cr16_print_operand_address. */ - *data = DM_FAR; - else - /* This call is (may be) made by - cr16_legitimate_address_p. */ - *data = ILLEGAL_DM; - } - } - return; - - case LABEL_REF: - /* 1 - indicates non-function symbol. */ - *code = 1; - return; - - case PLUS: - case MINUS: - /* Look into the tree nodes. */ - if (GET_CODE (XEXP (x, 0)) == CONST_INT) - cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const); - else if (GET_CODE (XEXP (x, 1)) == CONST_INT) - cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const); - return; - default: - return; - } -} - -/* Decompose Address - This function decomposes the address returns the type of address - as defined in enum cr16_addrtype. It also fills the parameter *out. - The decomposed address can be used for two purposes. One to - check if the address is valid and second to print the address - operand. - - Following tables list valid address supported in CR16C/C+ architectures. - Legend: - aN : Absoulte address N-bit address - R : One 16-bit register - RP : Consecutive two 16-bit registers or one 32-bit register - I : One 32-bit register - dispN : Signed displacement of N-bits - - ----Code addresses---- - Branch operands: - disp9 : CR16_ABSOLUTE (disp) - disp17 : CR16_ABSOLUTE (disp) - disp25 : CR16_ABSOLUTE (disp) - RP + disp25 : CR16_REGP_REL (base, disp) - - Jump operands: - RP : CR16_REGP_REL (base, disp=0) - a24 : CR16_ABSOLUTE (disp) - - ----Data addresses---- - a20 : CR16_ABSOLUTE (disp) near (1M) - a24 : CR16_ABSOLUTE (disp) medium (16M) - R + d20 : CR16_REG_REL (base, disp) near (1M+64K) - RP + d4 : CR16_REGP_REL (base, disp) far (4G) - RP + d16 : CR16_REGP_REL (base, disp) far (4G) - RP + d20 : CR16_REGP_REL (base, disp) far (4G) - I : *** Valid but port does not support this - I + a20 : *** Valid but port does not support this - I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G) - I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G) - - Decomposing Data model in case of absolute address. - - Target Option Address type Resultant Data ref type - ---------------------- ------------ ----------------------- - CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT - CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT - CR16_TARGET_MODEL_NEAR ABS24 Invalid - CR16_TARGET_MODEL_NEAR IMM32 Invalid - - CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT - CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT - CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR - CR16_TARGET_MODEL_MEDIUM IMM32 Invalid - - CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT - CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT - CR16_TARGET_MODEL_FAR ABS24 DM_FAR - CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */ -enum cr16_addrtype -cr16_decompose_address (rtx addr, struct cr16_address *out, - bool debug_print, bool treat_as_const) -{ - rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX; - enum data_model_type data = ILLEGAL_DM; - int code = -1; - enum cr16_addrtype retval = CR16_INVALID; - - switch (GET_CODE (addr)) - { - case CONST_INT: - /* Absolute address (known at compile time). */ - code = 0; - if (debug_print) - fprintf (stderr, "\ncode:%d", code); - disp = addr; - - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - } - - if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20)) - { - data = DM_DEFAULT; - if (debug_print) - fprintf (stderr, "\ndata:%d", data); - retval = CR16_ABSOLUTE; - } - else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24)) - { - if (!CR16_TARGET_DATA_NEAR) - { - data = DM_FAR; - if (debug_print) - fprintf (stderr, "\ndata:%d", data); - retval = CR16_ABSOLUTE; - } - else - return CR16_INVALID; /* ABS24 is not support in NEAR model. */ - } - else - return CR16_INVALID; - break; - - case CONST: - /* A CONST is an expression of PLUS or MINUS with - CONST_INT, SYMBOL_REF or LABEL_REF. This is the - result of assembly-time arithmetic computation. */ - retval = CR16_ABSOLUTE; - disp = addr; - /* Call the helper function to check the validity. */ - cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const); - if ((code == 0) && (data == ILLEGAL_DM)) - /* CONST is not valid code or data address. */ - return CR16_INVALID; - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - fprintf (stderr, "\ncode:%d", code); - fprintf (stderr, "\ndata:%d", data); - } - break; - - case LABEL_REF: - retval = CR16_ABSOLUTE; - disp = addr; - /* 1 - indicates non-function symbol. */ - code = 1; - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - fprintf (stderr, "\ncode:%d", code); - } - break; - - case SYMBOL_REF: - /* Absolute address (known at link time). */ - retval = CR16_ABSOLUTE; - disp = addr; - /* This is a code address if symbol_ref is a function. */ - /* 2 indicates func sym. */ - code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0; - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - fprintf (stderr, "\ncode:%d", code); - } - /* If not function ref then check if valid data ref. */ - if (code == 0) - { - if (CR16_TARGET_DATA_NEAR) - data = DM_DEFAULT; - else if (CR16_TARGET_DATA_MEDIUM) - data = DM_FAR; - else if (CR16_TARGET_DATA_FAR) - { - if (treat_as_const) - /* This will be used only for printing the - qualifier. This call is (may be) made - by cr16_print_operand_address. */ - data = DM_FAR; - else - /* This call is (may be) made by - cr16_legitimate_address_p. */ - return CR16_INVALID; - } - else - data = DM_DEFAULT; - } - if (debug_print) - fprintf (stderr, "\ndata:%d", data); - break; - - case REG: - case SUBREG: - /* Register relative address. */ - /* Assume REG fits in a single register. */ - retval = CR16_REG_REL; - if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD) - if (!LONG_REG_P (REGNO (addr))) - /* REG will result in reg pair. */ - retval = CR16_REGP_REL; - base = addr; - if (debug_print) - { - fprintf (stderr, "\nbase:"); - debug_rtx (base); - } - break; - - case PLUS: - switch (GET_CODE (XEXP (addr, 0))) - { - case REG: - case SUBREG: - /* REG + DISP20. */ - /* All Reg relative addresses having a displacement needs - to fit in 20-bits. */ - disp = XEXP (addr, 1); - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - } - switch (GET_CODE (XEXP (addr, 1))) - { - case CONST_INT: - /* Shall fit in 20-bits. */ - if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20)) - return CR16_INVALID; - code = 0; - if (debug_print) - fprintf (stderr, "\ncode:%d", code); - break; - - case UNSPEC: - switch (XINT (XEXP (addr, 1), 1)) - { - case UNSPEC_LIBRARY_OFFSET: - default: - gcc_unreachable (); - } - break; - - case LABEL_REF: - case SYMBOL_REF: - case CONST: - /* This is also a valid expression for address. - However, we cannot ascertain if the resultant - displacement will be valid 20-bit value. Therefore, - lets not allow such an expression for now. This will - be updated when we find a way to validate this - expression as legitimate address. - Till then fall through CR16_INVALID. */ - default: - return CR16_INVALID; - } - - /* Now check if REG can fit into single or pair regs. */ - retval = CR16_REG_REL; - base = XEXP (addr, 0); - if (debug_print) - { - fprintf (stderr, "\nbase:"); - debug_rtx (base); - } - if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD) - { - if (!LONG_REG_P (REGNO ((XEXP (addr, 0))))) - /* REG will result in reg pair. */ - retval = CR16_REGP_REL; - } - break; - - case PLUS: - /* Valid expr: - plus - /\ - / \ - plus idx - /\ - / \ - reg const_int - - Check if the operand 1 is valid index register. */ - data = ILLEGAL_DM; - if (debug_print) - fprintf (stderr, "\ndata:%d", data); - switch (GET_CODE (XEXP (addr, 1))) - { - case REG: - case SUBREG: - if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1))) - return CR16_INVALID; - /* OK. REG is a valid index register. */ - index = XEXP (addr, 1); - if (debug_print) - { - fprintf (stderr, "\nindex:"); - debug_rtx (index); - } - break; - default: - return CR16_INVALID; - } - /* Check if operand 0 of operand 0 is REGP. */ - switch (GET_CODE (XEXP (XEXP (addr, 0), 0))) - { - case REG: - case SUBREG: - /* Now check if REG is a REGP and not in LONG regs. */ - if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0))) - > BITS_PER_WORD) - { - if (REGNO (XEXP (XEXP (addr, 0), 0)) - >= CR16_FIRST_DWORD_REGISTER) - return CR16_INVALID; - base = XEXP (XEXP (addr, 0), 0); - if (debug_print) - { - fprintf (stderr, "\nbase:"); - debug_rtx (base); - } - } - else - return CR16_INVALID; - break; - default: - return CR16_INVALID; - } - /* Now check if the operand 1 of operand 0 is const_int. */ - if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) - { - disp = XEXP (XEXP (addr, 0), 1); - if (debug_print) - { - fprintf (stderr, "\ndisp:"); - debug_rtx (disp); - } - if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20)) - return CR16_INVALID; - } - else - return CR16_INVALID; - retval = CR16_INDEX_REGP_REL; - break; - default: - return CR16_INVALID; - } - break; - - default: - return CR16_INVALID; - } - - /* Check if the base and index registers are valid. */ - if (base && !(cr16_addr_reg_p (base))) - return CR16_INVALID; - if (base && !(CR16_REG_OK_FOR_BASE_P (base))) - return CR16_INVALID; - if (index && !(REG_OK_FOR_INDEX_P (index))) - return CR16_INVALID; - - /* Write the decomposition to out parameter. */ - out->base = base; - out->disp = disp; - out->index = index; - out->data = data; - out->code = code; - - return retval; -} - -/* Return non-zero value if 'x' is legitimate PIC operand - when generating PIC code. */ -int -legitimate_pic_operand_p (rtx x) -{ - switch (GET_CODE (x)) - { - case SYMBOL_REF: - return 0; - case LABEL_REF: - return 0; - case CONST: - /* REVISIT: Use something like symbol_referenced_p. */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF - || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) - && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)) - return 0; - break; - case MEM: - return legitimate_pic_operand_p (XEXP (x, 0)); - default: - break; - } - return 1; -} - -/* Convert a non-PIC address in `orig' to a PIC address in `reg'. - - Input Output (-f pic) Output (-f PIC) - orig reg - - C1 symbol symbol@BRO (r12) symbol@GOT (r12) - - C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12) - - NOTE: @BRO is added using unspec:BRO - NOTE: @GOT is added using unspec:GOT. */ -rtx -legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED, - rtx reg) -{ - /* First handle a simple SYMBOL_REF or LABEL_REF. */ - if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) - { - if (reg == 0) - reg = gen_reg_rtx (Pmode); - - if (flag_pic == NEAR_PIC) - { - /* Unspec to handle -fpic option. */ - emit_insn (gen_unspec_bro_addr (reg, orig)); - emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx)); - } - else if (flag_pic == FAR_PIC) - { - /* Unspec to handle -fPIC option. */ - emit_insn (gen_unspec_got_addr (reg, orig)); - } - return reg; - } - else if (GET_CODE (orig) == CONST) - { - /* To handle (symbol + offset). */ - rtx base, offset; - - if (GET_CODE (XEXP (orig, 0)) == PLUS - && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) - return orig; - - if (reg == 0) - { - gcc_assert (can_create_pseudo_p ()); - reg = gen_reg_rtx (Pmode); - } - - gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); - - base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg); - offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, - base == reg ? 0 : reg); - - /* REVISIT: Optimize for const-offsets. */ - emit_insn (gen_addsi3 (reg, base, offset)); - - return reg; - } - return orig; -} - -/* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */ -static bool -cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, - rtx addr, bool strict) -{ - enum cr16_addrtype addrtype; - struct cr16_address address; - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, - "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d", - GET_MODE_NAME (mode), strict); - debug_rtx (addr); - } - addrtype = cr16_decompose_address (addr, &address, - (TARGET_DEBUG_ADDR ? 1 : 0), FALSE); - - if (TARGET_DEBUG_ADDR) - { - const char *typestr; - - switch (addrtype) - { - case CR16_INVALID: - typestr = "invalid"; - break; - case CR16_ABSOLUTE: - typestr = "absolute"; - break; - case CR16_REG_REL: - typestr = "register relative"; - break; - case CR16_REGP_REL: - typestr = "register pair relative"; - break; - case CR16_INDEX_REGP_REL: - typestr = "index + register pair relative"; - break; - default: - gcc_unreachable (); - } - fprintf (stderr, "\ncr16 address type: %s\n", typestr); - } - - if (addrtype == CR16_INVALID) - return FALSE; - - if (strict) - { - if (address.base - && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode)) - { - if (TARGET_DEBUG_ADDR) - fprintf (stderr, "base register not strict\n"); - return FALSE; - } - if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index))) - { - if (TARGET_DEBUG_ADDR) - fprintf (stderr, "index register not strict\n"); - return FALSE; - } - } - - /* Return true if addressing mode is register relative. */ - if (flag_pic) - { - if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL) - return TRUE; - else - return FALSE; - } - - return TRUE; -} - -/* Routines to compute costs. */ - -/* Return cost of the memory address x. */ -static int -cr16_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED, - addr_space_t as ATTRIBUTE_UNUSED, - bool speed ATTRIBUTE_UNUSED) -{ - enum cr16_addrtype addrtype; - struct cr16_address address; - int cost = 2; - - addrtype = cr16_decompose_address (addr, &address, 0, FALSE); - - gcc_assert (addrtype != CR16_INVALID); - - /* CR16_ABSOLUTE : 3 - CR16_REG_REL (disp !=0) : 4 - CR16_REG_REL (disp ==0) : 5 - CR16_REGP_REL (disp !=0) : 6 - CR16_REGP_REL (disp ==0) : 7 - CR16_INDEX_REGP_REL (disp !=0) : 8 - CR16_INDEX_REGP_REL (disp ==0) : 9. */ - switch (addrtype) - { - case CR16_ABSOLUTE: - cost += 1; - break; - case CR16_REGP_REL: - cost += 2; - /* Fall through. */ - case CR16_REG_REL: - cost += 3; - if (address.disp) - cost -= 1; - break; - case CR16_INDEX_REGP_REL: - cost += 7; - if (address.disp) - cost -= 1; - default: - break; - } - - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost); - debug_rtx (addr); - } - - return cost; -} - - -/* Implement `TARGET_REGISTER_MOVE_COST'. */ -static int -cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, - reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to) -{ - return (to != GENERAL_REGS ? 8 : 2); -} - -/* Implement `TARGET_MEMORY_MOVE_COST'. */ - -/* Return the cost of moving data of mode MODE between a register of class - CLASS and memory; IN is zero if the value is to be written to memory, - nonzero if it is to be read in. This cost is relative to those in - REGISTER_MOVE_COST. */ -static int -cr16_memory_move_cost (machine_mode mode, - reg_class_t rclass ATTRIBUTE_UNUSED, - bool in ATTRIBUTE_UNUSED) -{ - /* One LD or ST takes twice the time of a simple reg-reg move. */ - if (reg_classes_intersect_p (rclass, GENERAL_REGS)) - return (4 * cr16_hard_regno_nregs (0, mode)); - else - return (100); -} - -/* Instruction output. */ - -/* Check if a const_double is ok for cr16 store-immediate instructions. */ -int -cr16_const_double_ok (rtx op) -{ - if (GET_MODE (op) == SFmode) - { - long l; - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l); - return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0; - } - - return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) && - (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0; -} - -/* Returns bit position of first 0 or 1 bit. - It is safe to assume val as 16-bit wide. */ -int -cr16_operand_bit_pos (int val, int bitval) -{ - int i; - if (bitval == 0) - val = ~val; - - for (i = 0; i < 16; i++) - if (val & (1 << i)) - break; - return i; -} - -/* Implements the macro PRINT_OPERAND defined in cr16.h. */ -static void -cr16_print_operand (FILE * file, rtx x, int code) -{ - int ptr_dereference = 0; - - switch (code) - { - case 'd': - { - const char *cr16_cmp_str; - switch (GET_CODE (x)) - { - /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg) - -> swap all non symmetric ops. */ - case EQ: - cr16_cmp_str = "eq"; - break; - case NE: - cr16_cmp_str = "ne"; - break; - case GT: - cr16_cmp_str = "lt"; - break; - case GTU: - cr16_cmp_str = "lo"; - break; - case LT: - cr16_cmp_str = "gt"; - break; - case LTU: - cr16_cmp_str = "hi"; - break; - case GE: - cr16_cmp_str = "le"; - break; - case GEU: - cr16_cmp_str = "ls"; - break; - case LE: - cr16_cmp_str = "ge"; - break; - case LEU: - cr16_cmp_str = "hs"; - break; - default: - gcc_unreachable (); - } - fprintf (file, "%s", cr16_cmp_str); - return; - } - case '$': - putc ('$', file); - return; - - case 'p': - if (GET_CODE (x) == REG) - { - /* For Push instructions, we should not print register pairs. */ - fprintf (file, "%s", reg_names[REGNO (x)]); - return; - } - break; - - case 'b': - /* Print the immediate address for bal - 'b' is used instead of 'a' to avoid compiler calling - the GO_IF_LEGITIMATE_ADDRESS which cannot - perform checks on const_int code addresses as it - assumes all const_int are data addresses. */ - fprintf (file, "0x%lx", INTVAL (x)); - return; - - case 'r': - /* Print bit position of first 0. */ - fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0)); - return; - - case 's': - /* Print bit position of first 1. */ - fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1)); - return; - case 'g': - /* 'g' is used for implicit mem: dereference. */ - ptr_dereference = 1; - /* FALLTHRU */ - case 'f': - case 0: - /* default. */ - switch (GET_CODE (x)) - { - case REG: - if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD) - { - if (LONG_REG_P (REGNO (x))) - fprintf (file, "(%s)", reg_names[REGNO (x)]); - else - fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1], - reg_names[REGNO (x)]); - } - else - fprintf (file, "%s", reg_names[REGNO (x)]); - return; - - case MEM: - output_address (GET_MODE (x), XEXP (x, 0)); - return; - - case CONST_DOUBLE: - { - long l; - - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l); - - fprintf (file, "$0x%lx", l); - return; - } - case CONST_INT: - { - fprintf (file, "$%ld", INTVAL (x)); - return; - } - case UNSPEC: - switch (XINT (x, 1)) - { - default: - gcc_unreachable (); - } - break; - - default: - if (!ptr_dereference) - { - putc ('$', file); - } - cr16_print_operand_address (file, VOIDmode, x); - return; - } - gcc_unreachable (); - default: - output_operand_lossage ("invalid %%xn code"); - } - - gcc_unreachable (); -} - -/* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */ - -static void -cr16_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr) -{ - enum cr16_addrtype addrtype; - struct cr16_address address; - - /* Decompose the address. Also ask it to treat address as constant. */ - addrtype = cr16_decompose_address (addr, &address, 0, TRUE); - - if (address.disp && GET_CODE (address.disp) == UNSPEC) - { - debug_rtx (addr); - } - - switch (addrtype) - { - case CR16_REG_REL: - if (address.disp) - { - if (GET_CODE (address.disp) == UNSPEC) - cr16_print_operand (file, address.disp, 0); - else - output_addr_const (file, address.disp); - } - else - fprintf (file, "0"); - fprintf (file, "(%s)", reg_names[REGNO (address.base)]); - break; - - case CR16_ABSOLUTE: - if (address.disp) - output_addr_const (file, address.disp); - else - fprintf (file, "0"); - break; - - case CR16_INDEX_REGP_REL: - fprintf (file, "[%s]", reg_names[REGNO (address.index)]); - /* Fall through. */ - case CR16_REGP_REL: - if (address.disp) - { - if (GET_CODE (address.disp) == UNSPEC) - cr16_print_operand (file, address.disp, 0); - else - output_addr_const (file, address.disp); - } - else - fprintf (file, "0"); - fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1], - reg_names[REGNO (address.base)]); - break; - default: - debug_rtx (addr); - gcc_unreachable (); - } - /* Add qualifiers to the address expression that was just printed. */ - if (flag_pic < NEAR_PIC && address.code == 0) - { - if (address.data == DM_FAR) - /* Addr contains SYMBOL_REF & far data ptr. */ - fprintf (file, "@l"); - else if (address.data == DM_DEFAULT) - /* Addr contains SYMBOL_REF & medium data ptr. */ - fprintf (file, "@m"); - /* Addr contains SYMBOL_REF & medium data ptr. */ - else if (address.data == DM_NEAR) - /* Addr contains SYMBOL_REF & near data ptr. */ - fprintf (file, "@s"); - } - else if (flag_pic == NEAR_PIC - && (address.code == 0) && (address.data == DM_FAR - || address.data == DM_DEFAULT - || address.data == DM_NEAR)) - { - fprintf (file, "@l"); - } - else if (flag_pic == NEAR_PIC && address.code == 2) - { - fprintf (file, "pic"); - } - else if (flag_pic == NEAR_PIC && address.code == 1) - { - fprintf (file, "@cpic"); - } - - else if (flag_pic == FAR_PIC && address.code == 2) - { - /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted - address ! GOTc tells assembler this symbol is a text-address - This needs to be fixed in such a way that this offset is done - only in the case where an address is being used for indirect jump - or call. Determining the potential usage of loadd is of course not - possible always. Eventually, this has to be fixed in the - processor. */ - fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]); - } - else if (flag_pic == FAR_PIC && address.code == 1) - { - fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]); - } - - else if (flag_pic == FAR_PIC && - (address.data == DM_FAR || address.data == DM_DEFAULT - || address.data == DM_NEAR)) - { - fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]); - } -} - -/* Machine description helper functions. */ - -/* Called from cr16.md. The return value depends on the parameter push_or_pop: - When push_or_pop is zero -> string for push instructions of prologue. - When push_or_pop is nonzero -> string for pop/popret/retx in epilogue. - Relies on the assumptions: - 1. RA is the last register to be saved. - 2. The maximal value of the counter is MAX_COUNT. */ -char * -cr16_prepare_push_pop_string (int push_or_pop) -{ - /* j is the number of registers being saved, takes care that there won't be - more than 8 in one push/pop instruction. */ - - /* For the register mask string. */ - static char one_inst_str[50]; - - /* i is the index of current_frame_info.save_regs[], going from 0 until - current_frame_info.last_reg_to_save. */ - int i, start_reg; - int word_cnt; - int print_ra; - char *return_str; - - /* For reversing on the push instructions if there are more than one. */ - char *temp_str; - - return_str = (char *) xmalloc (160); - temp_str = (char *) xmalloc (160); - - /* Initialize. */ - memset (return_str, 0, 3); - - i = 0; - while (i <= current_frame_info.last_reg_to_save) - { - /* Prepare mask for one instruction. */ - one_inst_str[0] = 0; - - /* To count number of words in one instruction. */ - word_cnt = 0; - start_reg = i; - print_ra = 0; - while ((word_cnt < MAX_COUNT) - && (i <= current_frame_info.last_reg_to_save)) - { - /* For each non consecutive save register, - a new instruction shall be generated. */ - if (!current_frame_info.save_regs[i]) - { - /* Move to next reg and break. */ - ++i; - break; - } - - if (i == RETURN_ADDRESS_REGNUM) - print_ra = 1; - else - { - /* Check especially if adding 2 does not cross the MAX_COUNT. */ - if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2)) - >= MAX_COUNT) - break; - /* Increase word count by 2 for long registers except RA. */ - word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2); - } - ++i; - } - - /* No need to generate any instruction as - no register or RA needs to be saved. */ - if ((word_cnt == 0) && (print_ra == 0)) - continue; - - /* Now prepare the instruction operands. */ - if (word_cnt > 0) - { - sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]); - if (print_ra) - strcat (one_inst_str, ", ra"); - } - else - strcat (one_inst_str, "ra"); - - if (push_or_pop == 1) - { - /* Pop instruction. */ - if (print_ra && !cr16_interrupt_function_p () - && !crtl->calls_eh_return) - /* Print popret if RA is saved and its not a interrupt - function. */ - strcpy (temp_str, "\n\tpopret\t"); - else - strcpy (temp_str, "\n\tpop\t"); - - strcat (temp_str, one_inst_str); - - /* Add the pop instruction list. */ - strcat (return_str, temp_str); - } - else - { - /* Push instruction. */ - strcpy (temp_str, "\n\tpush\t"); - strcat (temp_str, one_inst_str); - - /* We need to reverse the order of the instructions if there - are more than one. (since the pop will not be reversed in - the epilogue. */ - strcat (temp_str, return_str); - strcpy (return_str, temp_str); - } - } - - if (push_or_pop == 1) - { - /* POP. */ - if (cr16_interrupt_function_p ()) - strcat (return_str, "\n\tretx\n"); - else if (crtl->calls_eh_return) - { - /* Add stack adjustment before returning to exception handler - NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */ - strcat (return_str, "\n\taddd\t (r5, r4), (sp)\t\n"); - strcat (return_str, "\n\tjump\t (ra)\n"); - - /* But before anything else, undo the adjustment addition done in - cr16_expand_epilogue (). */ - strcpy (temp_str, "\n\tsubd\t (r5, r4), (sp)\t\n"); - strcat (temp_str, return_str); - strcpy (return_str, temp_str); - } - else if (!FUNC_IS_NORETURN_P (current_function_decl) - && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM])) - strcat (return_str, "\n\tjump\t (ra)\n"); - } - - /* Skip the newline and the tab in the start of return_str. */ - return_str += 2; - return return_str; -} - - -/* Generate DWARF2 annotation for multi-push instruction. */ -static void -cr16_create_dwarf_for_multi_push (rtx insn) -{ - rtx dwarf, reg, tmp; - int i, j, from, to, word_cnt, dwarf_par_index, inc; - machine_mode mode; - int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0; - - for (i = 0; i <= current_frame_info.last_reg_to_save; ++i) - { - if (current_frame_info.save_regs[i]) - { - ++num_regs; - if (i < CR16_FIRST_DWORD_REGISTER) - total_push_bytes += 2; - else - total_push_bytes += 4; - } - } - - if (!num_regs) - return; - - dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1)); - dwarf_par_index = num_regs; - - from = current_frame_info.last_reg_to_save + 1; - to = current_frame_info.last_reg_to_save; - word_cnt = 0; - - for (i = current_frame_info.last_reg_to_save; i >= 0;) - { - if (!current_frame_info.save_regs[i] || i == 0 || split_here) - { - /* This block of regs is pushed in one instruction. */ - if (i == 0 && current_frame_info.save_regs[i]) - from = 0; - - for (j = to; j >= from; --j) - { - if (j < CR16_FIRST_DWORD_REGISTER) - { - mode = HImode; - inc = 1; - } - else - { - mode = SImode; - inc = 2; - } - reg = gen_rtx_REG (mode, j); - offset += 2 * inc; - tmp = gen_rtx_SET (gen_frame_mem (mode, - plus_constant - (Pmode, stack_pointer_rtx, - total_push_bytes - offset)), - reg); - RTX_FRAME_RELATED_P (tmp) = 1; - XVECEXP (dwarf, 0, dwarf_par_index--) = tmp; - } - from = i; - to = --i; - split_here = 0; - word_cnt = 0; - continue; - } - - if (i != RETURN_ADDRESS_REGNUM) - { - inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2; - if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i) - { - split_here = 1; - from = i; - continue; - } - word_cnt += inc; - } - - from = i--; - } - - tmp = gen_rtx_SET (stack_pointer_rtx, - gen_rtx_PLUS (SImode, stack_pointer_rtx, - GEN_INT (-offset))); - RTX_FRAME_RELATED_P (tmp) = 1; - XVECEXP (dwarf, 0, 0) = tmp; - - add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf); -} - -/* -CompactRISC CR16 Architecture stack layout: - - 0 +--------------------- - | - . - . - | - +==================== Sp (x) = Ap (x+1) - A | Args for functions - | | called by X and Dynamically - | | Dynamic allocations allocated and - | | (alloca, variable deallocated - Stack | length arrays). - grows +-------------------- Fp (x) - down| | Local variables of X - ward| +-------------------- - | | Regs saved for X-1 - | +==================== Sp (x-1) = Ap (x) - | Args for func X - | pushed by X-1 - +-------------------- Fp (x-1) - | - | - V -*/ -void -cr16_expand_prologue (void) -{ - rtx insn; - - cr16_compute_frame (); - cr16_compute_save_regs (); - - /* If there is no need in push and adjustment to sp, return. */ - if ((current_frame_info.total_size + current_frame_info.reg_size) == 0) - return; - - if (current_frame_info.last_reg_to_save != -1) - { - /* If there are registers to push. */ - insn = emit_insn (gen_push_for_prologue - (GEN_INT (current_frame_info.reg_size))); - cr16_create_dwarf_for_multi_push (insn); - RTX_FRAME_RELATED_P (insn) = 1; - } - - - if (current_frame_info.total_size > 0) - { - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-current_frame_info.total_size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - if (frame_pointer_needed) - { - /* Initialize the frame pointer with the value of the stack pointer - pointing now to the locals. */ - insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - } -} - -/* Generate insn that updates the stack for local variables and padding - for registers we save. - Generate the appropriate return insn. */ -void -cr16_expand_epilogue (void) -{ - rtx insn; - - /* Nonzero if we need to return and pop only RA. This will generate a - different insn. This differentiate is for the peepholes for call as - last statement in function. */ - int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM] - && (current_frame_info.reg_size - == CR16_UNITS_PER_DWORD)); - - if (frame_pointer_needed) - { - /* Restore the stack pointer with the frame pointers value. */ - insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); - } - - if (current_frame_info.total_size > 0) - { - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (current_frame_info.total_size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - - if (crtl->calls_eh_return) - { - /* Add this here so that (r5, r4) is actually loaded with the adjustment - value; otherwise, the load might be optimized away... - NOTE: remember to subtract the adjustment before popping the regs - and add it back before returning. */ - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - EH_RETURN_STACKADJ_RTX)); - } - - if (cr16_interrupt_function_p ()) - { - insn = emit_jump_insn (gen_interrupt_return ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (crtl->calls_eh_return) - { - /* Special case, pop what's necessary, adjust SP and jump to (RA). */ - insn = emit_jump_insn (gen_pop_and_popret_return - (GEN_INT (current_frame_info.reg_size))); - RTX_FRAME_RELATED_P (insn) = 1; - } - else if (current_frame_info.last_reg_to_save == -1) - /* Nothing to pop. */ - /* Don't output jump for interrupt routine, only retx. */ - emit_jump_insn (gen_jump_return ()); - else if (only_popret_RA) - { - insn = emit_jump_insn (gen_popret_RA_return ()); - RTX_FRAME_RELATED_P (insn) = 1; - } - else - { - insn = emit_jump_insn (gen_pop_and_popret_return - (GEN_INT (current_frame_info.reg_size))); - RTX_FRAME_RELATED_P (insn) = 1; - } -} - -/* Implements FRAME_POINTER_REQUIRED. */ -static bool -cr16_frame_pointer_required (void) -{ - return (cfun->calls_alloca || crtl->calls_eh_return - || cfun->has_nonlocal_label || crtl->calls_eh_return); -} - -static bool -cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) -{ - return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true); -} - - -/* A C compound statement that attempts to replace X with - a valid memory address for an operand of mode MODE. WIN - will be a C statement label elsewhere in the code. - X will always be the result of a call to break_out_memory_refs (), - and OLDX will be the operand that was given to that function to - produce X. - The code generated by this macro should not alter the - substructure of X. If it transforms X into a more legitimate form, - it should assign X (which will always be a C variable) a new value. */ -static rtx -cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED, - machine_mode mode ATTRIBUTE_UNUSED) -{ - if (flag_pic) - return legitimize_pic_address (orig_x, mode, NULL_RTX); - else - return x; -} - -/* Implement TARGET_LEGITIMATE_CONSTANT_P - Nonzero if X is a legitimate constant for an immediate - operand on the target machine. You can assume that X - satisfies CONSTANT_P. In cr16c treat legitimize float - constant as an immediate operand. */ -static bool -cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, - rtx x ATTRIBUTE_UNUSED) -{ - return 1; -} - -static scalar_int_mode -cr16_unwind_word_mode (void) -{ - return SImode; -} - -/* Helper function for md file. This function is used to emit arithmetic - DI instructions. The argument "num" decides which instruction to be - printed. */ -const char * -cr16_emit_add_sub_di (rtx *operands, enum rtx_code code) -{ - rtx lo_op[2] ; - rtx hi0_op[2] ; - rtx hi1_op[2] ; - - lo_op[0] = gen_lowpart (SImode, operands[0]); - hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4); - hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6); - - lo_op[1] = gen_lowpart (SImode, operands[2]); - hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4); - hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6); - - switch (code) - { - case PLUS: - { - output_asm_insn ("addd\t%1, %0", lo_op) ; - output_asm_insn ("addcw\t%1, %0", hi0_op) ; - output_asm_insn ("addcw\t%1, %0", hi1_op) ; - break; - } - case MINUS: - { - output_asm_insn ("subd\t%1, %0", lo_op) ; - output_asm_insn ("subcw\t%1, %0", hi0_op) ; - output_asm_insn ("subcw\t%1, %0", hi1_op) ; - break; - } - default: - break; - } - - return ""; -} - - -/* Helper function for md file. This function is used to emit logical - DI instructions. The argument "num" decides which instruction to be - printed. */ -const char * -cr16_emit_logical_di (rtx *operands, enum rtx_code code) -{ - rtx lo_op[2] ; - rtx hi_op[2] ; - - lo_op[0] = gen_lowpart (SImode, operands[0]); - hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4); - - lo_op[1] = gen_lowpart (SImode, operands[2]); - hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4); - - switch (code) - { - case AND: - { - output_asm_insn ("andd\t%1, %0", lo_op) ; - output_asm_insn ("andd\t%1, %0", hi_op) ; - return ""; - } - case IOR: - { - output_asm_insn ("ord\t%1, %0", lo_op) ; - output_asm_insn ("ord\t%1, %0", hi_op) ; - return ""; - } - case XOR: - { - output_asm_insn ("xord\t%1, %0", lo_op) ; - output_asm_insn ("xord\t%1, %0", hi_op) ; - return ""; - } - default: - break; - } - - return ""; -} - -/* Implement PUSH_ROUNDING. */ - -poly_int64 -cr16_push_rounding (poly_int64 bytes) -{ - return (bytes + 1) & ~1; -} - -/* Initialize 'targetm' variable which contains pointers to functions - and data relating to the target machine. */ - -struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/cr16/cr16.h b/gcc/config/cr16/cr16.h deleted file mode 100644 index 100bb4f..0000000 --- a/gcc/config/cr16/cr16.h +++ /dev/null @@ -1,556 +0,0 @@ -/* Definitions of target machine for GNU compiler, for CR16. - Copyright (C) 2012-2022 Free Software Foundation, Inc. - Contributed by KPIT Cummins Infosystems Limited. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING3. If not see - <http://www.gnu.org/licenses/>. */ - -#ifndef GCC_CR16_H -#define GCC_CR16_H - -#define OBJECT_FORMAT_ELF - -/* Controlling the driver. */ - -/* The GNU C++ standard library requires that these macros be defined. */ -#undef CPLUSPLUS_CPP_SPEC -#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)" - -#undef STARTFILE_SPEC -#define STARTFILE_SPEC "crt1.o%s crti.o%s crtbegin.o%s crtlibid.o%s" - -#undef ENDFILE_SPEC -#define ENDFILE_SPEC "crtend.o%s crtn.o%s" - -#undef MATH_LIBRARY -#define MATH_LIBRARY "" - -#undef LIB_SPEC -#define LIB_SPEC "-( -lc %{msim*:-lsim}%{!msim*:-lnosys} -) \ -%{msim*:%{!T*:-Tsim.ld}} \ -%{!T*:%{!msim*: %{-Telf32cr16.x}}}" - -/* Run-time target specification. */ -#ifndef TARGET_CPU_CPP_BUILTINS -#define TARGET_CPU_CPP_BUILTINS() \ -do \ - { \ - builtin_define ("__CR__"); \ - builtin_define ("__CR16__"); \ - builtin_define ("__CR16C__"); \ - if (TARGET_CR16CP) \ - builtin_define ("__CR16CP__"); \ - else \ - builtin_define ("__CR16CSTD__"); \ - if (CR16_TARGET_DATA_NEAR) \ - builtin_define ("__DATA_NEAR__"); \ - if (CR16_TARGET_DATA_MEDIUM) \ - builtin_define ("__DATA_MEDIUM__"); \ - if (CR16_TARGET_DATA_FAR) \ - builtin_define ("__DATA_FAR__"); \ - if (TARGET_INT32) \ - builtin_define ("__INT32__"); \ - } \ -while (0) -#endif - -/* Force the generation of dwarf .debug_frame sections even if not - compiling -g. This guarantees that we can unwind the stack. */ -#define DWARF2_FRAME_INFO 1 - -#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -/* Generate .file/.loc directives, so that the assembler generates the - line table. */ -#define DWARF2_ASM_LINE_DEBUG_INFO 1 - -#define CR16_TARGET_DATA_NEAR cr16_is_data_model (DM_NEAR) -#define CR16_TARGET_DATA_MEDIUM cr16_is_data_model (DM_DEFAULT) -#define CR16_TARGET_DATA_FAR cr16_is_data_model (DM_FAR) - -/* Storage layout. */ -#define BITS_BIG_ENDIAN 0 - -#define BYTES_BIG_ENDIAN 0 - -#define WORDS_BIG_ENDIAN 0 - -#define UNITS_PER_WORD 2 - -/* Units per 32-bit (DWORD). */ -#define CR16_UNITS_PER_DWORD 4 - -#define POINTER_SIZE 32 - -#define PARM_BOUNDARY 16 - -#define STACK_BOUNDARY (MAX (BIGGEST_ALIGNMENT, PARM_BOUNDARY)) - -#define FUNCTION_BOUNDARY BIGGEST_ALIGNMENT - -/* Biggest alignment on CR16C+ is 32-bit as internal bus is AMBA based - where as CR16C is proprietary internal bus architecture. */ -#define BIGGEST_ALIGNMENT ((TARGET_CR16CP) ? 32 : 16) - -#define MAX_FIXED_MODE_SIZE 64 - -/* In CR16 arrays of chars are word-aligned, so strcpy () will be faster. */ -#define DATA_ALIGNMENT(TYPE, ALIGN) \ - (((TREE_CODE (TYPE) == ARRAY_TYPE) \ - && (TYPE_MODE (TREE_TYPE (TYPE)) == QImode) \ - && ((ALIGN) < BITS_PER_WORD)) \ - ? (BITS_PER_WORD) : (ALIGN)) - -#define STRICT_ALIGNMENT 0 - -#define PCC_BITFIELD_TYPE_MATTERS 1 - -/* Layout of source language data types. */ -#define INT_TYPE_SIZE (TARGET_INT32 ? 32 : 16) - -#define SHORT_TYPE_SIZE 16 - -#define LONG_TYPE_SIZE 32 - -#define LONG_LONG_TYPE_SIZE 64 - -#define FLOAT_TYPE_SIZE 32 - -#define DOUBLE_TYPE_SIZE 64 - -#define LONG_DOUBLE_TYPE_SIZE 64 - -#define DEFAULT_SIGNED_CHAR 1 - -#define SIZE_TYPE "long unsigned int" - -#define PTRDIFF_TYPE "long int" - -#define WCHAR_TYPE "short unsigned int" - -#define WCHAR_TYPE_SIZE 16 - -/* By default, the C++ compiler will use the lowest bit of the pointer - to function to indicate a pointer-to-member-function points to a - virtual member function. However, in CR architecture FUNCTION_BOUNDARY - indicates function addresses are always even, but function pointers can be - odd (after right-shifting them when loading them into a register), and the - default doesn't work. In that case, the lowest bit of the delta - field will be used (the remainder of the field is shifted to the left). */ -#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta - -/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return - values must be in memory. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Register usage. */ - -/* First 32-bit register is R12. */ -#define CR16_FIRST_DWORD_REGISTER 12 - -#define FIRST_PSEUDO_REGISTER 16 - -/* 1 for registers that have pervasive standard uses - and are not available for the register allocator. - On the CR16, only the stack pointer (r15) is such. */ -#define FIXED_REGISTERS \ - { \ - /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10. */ \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ - /* r11 r12 r13 ra sp. */ \ - 0, 0, 0, 0, 1 \ - } - -/* 1 for registers not available across function calls. - These must include the FIXED_REGISTERS and also any - registers that can be used without being saved. - The latter must include the registers where values are returned - and the register where structure-value addresses are passed. - - On the CR16, calls clobbers r0-r6 (scratch registers), - ra (the return address) and sp (the stack pointer). */ -#define CALL_USED_REGISTERS \ - { \ - /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10. */ \ - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \ - /* r11 r12 r13 ra sp. */ \ - 0, 0, 0, 1, 1 \ - } - -/* Returns 1 if the register is longer than word size, 0 otherwise. */ -#define LONG_REG_P(REGNO) \ - (targetm.hard_regno_nregs (REGNO, \ - GET_MODE_WIDER_MODE (word_mode).require ()) == 1) - -/* Interrupt functions can only use registers that have already been - saved by the prologue, even if they would normally be call-clobbered - Check if sizes are same and then check if it is possible to rename. */ -#define HARD_REGNO_RENAME_OK(SRC, DEST) \ - (!cr16_interrupt_function_p () || (df_regs_ever_live_p (DEST))) - -/* Exception handling stuff. */ - -/*To ensure correct dwarf unwinding. */ -#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((optimize ("no-gcse","no-dse"))) - -#define gen_rtx_RA gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM) - -/* Use (r8,r7) and (r10,r9) to pass exception handling information. */ -#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? (N*2 + 7) : INVALID_REGNUM) - -#define DWARF2_UNWIND_INFO 1 - -/* (r5,r4) holds a stack adjustment for returning to a handler. */ -#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 4) - -#define EH_RETURN_HANDLER_RTX \ - gen_rtx_MEM (Pmode, plus_constant (Pmode, arg_pointer_rtx, -4)) - -#define INCOMING_RETURN_ADDR_RTX gen_rtx_RA - -#define DWARF_FRAME_RETURN_COLUMN \ - DWARF_FRAME_REGNUM (RETURN_ADDRESS_REGNUM) - -#define INCOMING_FRAME_SP_OFFSET 0 -#define FRAME_POINTER_CFA_OFFSET(FNDECL) 0 - -/* A C expression whose value is RTL representing the value of the return - address for the frame COUNT steps up from the current frame. */ -#define RETURN_ADDR_RTX(COUNT, FRAME) \ - (COUNT == 0) ? gen_rtx_PLUS (Pmode, gen_rtx_RA, gen_rtx_RA) \ - : const0_rtx - -enum reg_class -{ - NO_REGS, - SHORT_REGS, - LONG_REGS, - NOSP_REGS, - DOUBLE_BASE_REGS, - GENERAL_REGS, - ALL_REGS, - LIM_REG_CLASSES -}; - -#define N_REG_CLASSES (int) LIM_REG_CLASSES - -#define REG_CLASS_NAMES \ - { \ - "NO_REGS", \ - "SHORT_REGS", \ - "LONG_REGS", \ - "NOSP_REGS", \ - "DOUBLE_BASE_REGS", \ - "GENERAL_REGS", \ - "ALL_REGS" \ - } - -#define REG_CLASS_CONTENTS \ - { \ - {0x00000000}, /* NO_REGS */ \ - {0x00000FFF}, /* SHORT_REGS : 0 - 11 */ \ - {0x0000F000}, /* LONG_REGS : 12 - 15 */ \ - {0x00007FFF}, /* NOSP_REGS : 0 - 14 */ \ - {0x0000F555}, /* DOUBLE_BASE_REGS : 2,4,6,8,10 */ \ - {0x0000FFFF}, /* GENERAL_REGS : 0 - 15 */ \ - {0x0000FFFF} /* ALL_REGS : 0 - 15 */ \ - } - -#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true - -#define REGNO_REG_CLASS(REGNO) cr16_regno_reg_class (REGNO) - -#define BASE_REG_CLASS GENERAL_REGS - -#define MODE_BASE_REG_CLASS(MODE) \ - (GET_MODE_SIZE (MODE) <= 4 ? (BASE_REG_CLASS) : (DOUBLE_BASE_REGS)) - -#define INDEX_REG_CLASS LONG_REGS - -#define CR16_REGNO_OK_FOR_BASE_P(REGNO) \ - (((REGNO) < FIRST_PSEUDO_REGISTER) \ - || (reg_renumber && ((unsigned) reg_renumber[REGNO] \ - < FIRST_PSEUDO_REGISTER))) - -/* Use even-numbered reg for 64-bit accesses. */ -#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ - (CR16_REGNO_OK_FOR_BASE_P(REGNO) && \ - ((GET_MODE_SIZE (MODE) > 4 && \ - (REGNO) < CR16_FIRST_DWORD_REGISTER) \ - ? (((REGNO) & 1) == 0) \ - : 1)) - -/* TODO: For now lets not support index addressing mode. */ -#define REGNO_OK_FOR_INDEX_P(REGNO) \ - (((REGNO >= CR16_FIRST_DWORD_REGISTER) \ - && ((REGNO) < FIRST_PSEUDO_REGISTER)) \ - || (reg_renumber \ - && (((unsigned) reg_renumber[REGNO] >= CR16_FIRST_DWORD_REGISTER) \ - && ((unsigned) reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))) \ - ) - -#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS - -/* The maximum number of consecutive registers of class CLASS needed to - hold a value of mode MODE. - On the CompactRISC architecture, the size of MODE in words. - The size of MODE in double words for the class LONG_REGS. - - The following check assumes if the class is not LONG_REGS, then - all (NO_REGS, SHORT_REGS, NOSP_REGS and GENERAL_REGS) other classes are - short. We may have to check if this can cause any degradation in - performance. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - (CLASS == LONG_REGS \ - ? (GET_MODE_SIZE (MODE) + CR16_UNITS_PER_DWORD - 1) / CR16_UNITS_PER_DWORD\ - : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) - -/* Macros to check the range of integers . These macros were used across - the port, majorly in constraints.md, predicates.md files. */ -#define SIGNED_INT_FITS_N_BITS(imm, N) \ - ((((imm) < ((HOST_WIDE_INT) 1 << ((N) - 1))) \ - && ((imm) >= -((HOST_WIDE_INT) 1 << ((N) - 1)))) ? 1 : 0) - -#define UNSIGNED_INT_FITS_N_BITS(imm, N) \ - (((imm) < ((HOST_WIDE_INT) 1 << (N)) && (imm) >= (HOST_WIDE_INT) 0) ? 1 : 0) - -#define IN_RANGE_P(VALUE, LOW, HIGH) \ - ((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW)) \ - && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) - -#define IN_RAN(VALUE, LOW, HIGH) \ - (((((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW)) \ - && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH)))) ? 1 : 0) - -/* This check is for sbit/cbit instruction. */ -#define OK_FOR_Z(OP) \ - ((GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST_INT) \ - || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG) \ - || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == PLUS \ - && GET_CODE (XEXP ((XEXP (OP, 0)), 0)) == REG \ - && GET_CODE (XEXP ((XEXP (OP, 0)), 1)) == CONST_INT)) - -/* Stack layout and calling conventions. */ -#define STACK_GROWS_DOWNWARD 1 - -#define STACK_POINTER_REGNUM 15 - -#define FRAME_POINTER_REGNUM 13 - -#define ARG_POINTER_REGNUM 12 - -#define STATIC_CHAIN_REGNUM 1 - -#define RETURN_ADDRESS_REGNUM 14 - -#define FIRST_PARM_OFFSET(FNDECL) 0 - -#define ELIMINABLE_REGS \ - { \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \ - } - -#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ - do \ - { \ - (OFFSET) = cr16_initial_elimination_offset ((FROM), (TO)); \ - } \ - while (0) - -/* Passing function arguments. */ - -#define ACCUMULATE_OUTGOING_ARGS 0 - -#define PUSH_ROUNDING(BYTES) cr16_push_rounding (BYTES) - -#ifndef CUMULATIVE_ARGS -struct cumulative_args -{ - int ints; - int last_parm_in_reg; -}; - -#define CUMULATIVE_ARGS struct cumulative_args -#endif - -/* On the CR16 architecture, Varargs routines should receive their parameters - on the stack. */ - -#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ - cr16_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME)) - -#define FUNCTION_ARG_REGNO_P(REGNO) cr16_function_arg_regno_p (REGNO) - -/* Generating code for profiling - NOT IMPLEMENTED. */ -#undef FUNCTION_PROFILER -#define FUNCTION_PROFILER(STREAM, LABELNO) \ -{ \ - sorry ("profiler support for CR16"); \ -} - -/* Trampolines for nested functions - NOT SUPPORTED. */ -#define TRAMPOLINE_SIZE 16 - -/* ADDRESSING MODES. */ - -#define CONSTANT_ADDRESS_P(X) \ - (GET_CODE (X) == LABEL_REF \ - || GET_CODE (X) == SYMBOL_REF \ - || GET_CODE (X) == CONST \ - || GET_CODE (X) == CONST_INT) - -#define MAX_REGS_PER_ADDRESS 2 - -#define HAVE_POST_INCREMENT 0 -#define HAVE_POST_DECREMENT 0 -#define HAVE_POST_MODIFY_DISP 0 -#define HAVE_POST_MODIFY_REG 0 - -#ifdef REG_OK_STRICT -#define CR16_REG_OK_FOR_BASE_P(X) CR16_REGNO_OK_FOR_BASE_P (REGNO (X)) -#define REG_MODE_OK_FOR_BASE_P(X, MODE) \ - REGNO_MODE_OK_FOR_BASE_P (REGNO(X), MODE) -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -#else /* not REG_OK_STRICT. */ -#define CR16_REG_OK_FOR_BASE_P(X) 1 -#define REG_MODE_OK_FOR_BASE_P(X, MODE) 1 -#define REG_OK_FOR_INDEX_P(X) 1 -#endif /* not REG_OK_STRICT. */ - -/* Assume best case (branch predicted). */ -#define BRANCH_COST(speed_p, predictable_p) 2 - -#define SLOW_BYTE_ACCESS 1 - -/* It is as good or better to call a constant function address than to - call an address kept in a register. */ -#define NO_FUNCTION_CSE 1 - -/* Dividing the output into sections. */ - -#define TEXT_SECTION_ASM_OP "\t.section\t.text" - -#define DATA_SECTION_ASM_OP "\t.section\t.data" - -#define BSS_SECTION_ASM_OP "\t.section\t.bss" - -/* Position independent code (PIC). */ -/* NEAR_PIC for -fpic option. */ - -#define NEAR_PIC 1 - -/* FAR_PIC for -fPIC option. */ - -#define FAR_PIC 2 - -#define PIC_OFFSET_TABLE_REGNUM 12 - -#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X) - -/* Assembler format. */ - -/* Character to start a comment. */ -#define ASM_COMMENT_START "#" - -#define GLOBAL_ASM_OP "\t.globl\t" - -#undef USER_LABEL_PREFIX -#define USER_LABEL_PREFIX "_" - -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(STREAM, NAME) \ - asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME)) - -#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL) \ - do \ - { \ - const char *rn = XSTR (SYMBOL, 0); \ - assemble_name (STREAM, rn); \ - if (SYMBOL_REF_FUNCTION_P (SYMBOL)) \ - { \ - fprintf ((STREAM), "@c"); \ - } \ - } \ - while (0) - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" - -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* Switch into a generic section. */ -#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section - -#undef INIT_SECTION_ASM_OP -#define INIT_SECTION_ASM_OP "\t.section\t.init" - -#undef FINI_SECTION_ASM_OP -#define FINI_SECTION_ASM_OP "\t.section\t.fini" - -/* Instruction output. */ - -#define REGISTER_NAMES \ - { \ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp" \ - } - -/* Output of dispatch tables. */ - -/* Revisit. No PC relative case as label expressions are not - properly supported in binutils else we could have done this: - #define CASE_VECTOR_PC_RELATIVE (optimize_size ? 1 : 0). */ -#define CASE_VECTOR_PC_RELATIVE 0 - -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ - ((GET_MODE (BODY) == QImode) \ - ? fprintf ((FILE), "\t.byte (.L%d-.L%d) >> 1\n", \ - VALUE, REL) \ - : fprintf ((FILE), "\t.word (.L%d-.L%d) >> 1\n", \ - VALUE, REL)) - -#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \ - asm_fprintf ((STREAM), "\t.long\t.L%d@c\n", (VALUE)) - -/* Alignment in assembler file. */ - -#define ASM_OUTPUT_ALIGN(STREAM, POWER) \ - asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER)) - -/* Miscellaneous parameters. */ - -#define CASE_VECTOR_MODE Pmode - -#define MOVE_MAX 4 - -#define STORE_FLAG_VALUE 1 - -#define Pmode SImode - -#define FUNCTION_MODE QImode - -/* Define this boolean macro(s) to indicate whether or not your architecture - has (un)conditional branches that can span all of memory. It is used in - conjunction with an optimization that partitions hot and cold basic blocks - into separate sections of the executable. - CR16 contains branch instructions that span whole address space. */ -#define HAS_LONG_COND_BRANCH 1 -#define HAS_LONG_UNCOND_BRANCH 1 - -#endif /* End of GCC_CR16_H. */ diff --git a/gcc/config/cr16/cr16.md b/gcc/config/cr16/cr16.md deleted file mode 100644 index 7ec7468..0000000 --- a/gcc/config/cr16/cr16.md +++ /dev/null @@ -1,1084 +0,0 @@ -;; GCC machine description for CR16. -;; Copyright (C) 2012-2022 Free Software Foundation, Inc. -;; Contributed by KPIT Cummins Infosystems Limited. - -;; This file is part of GCC. - -;; GCC is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; GCC is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Register numbers -(define_constants - [(SP_REGNUM 15); Stack pointer - (RA_REGNUM 14); Return address - ] -) - -;; Predicates & Constraints -(include "predicates.md") -(include "constraints.md") - -;; UNSPEC usage -(define_constants - [(UNSPEC_PIC_ADDR 0) - (UNSPEC_PIC_LOAD_ADDR 1) - (UNSPEC_LIBRARY_OFFSET 2) - (UNSPEC_SH_LIB_PUSH_R12 3) - (UNSPEC_SH_LIB_POP_R12 4) - (UNSPEC_RETURN_ADDR 5) - ] -) - -;; Attributes -(define_attr "length" "" (const_int 2)) - -(define_asm_attributes - [(set_attr "length" "2")] -) - -;; Mode Macro Definitions -(define_mode_iterator CR16IM [QI HI SI]) -(define_mode_iterator LONG [SI SF]) -(define_mode_iterator ALLMTD [QI HI SI SF DI DF]) -(define_mode_iterator DOUBLE [DI DF]) -(define_mode_iterator SHORT [QI HI]) -(define_mode_attr tIsa [(QI "b") (HI "w") (SI "d") (SF "d")]) -(define_mode_attr lImmArith [(QI "4") (HI "4") (SI "6") (SF "6")]) -(define_mode_attr lImmArithD [(QI "4") (HI "4") (SI "6") (SF "6") (DI "12") (DF "12")]) -(define_mode_attr iF [(QI "i") (HI "i") (SI "i") (SF "F")]) -(define_mode_attr iFD [(DI "i") (DF "F")]) -(define_mode_attr LL [(QI "L") (HI "L")]) -(define_mode_attr shImmBits [(QI "3") (HI "4") (SI "5")]) - -; In QI mode we push 2 bytes instead of 1 byte. -(define_mode_attr pushCnstr [(QI "X") (HI "<") (SI "<") (SF "<") (DI "<") (DF "<")]) - -; tpush will be used to generate the 'number of registers to push' in the -; push instruction. -(define_mode_attr tpush [(QI "1") (HI "1") (SI "2") (SF "2") (DI "4") (DF "4")]) - -;; Code Macro Definitions -(define_code_attr sIsa [(sign_extend "") (zero_extend "u")]) -(define_code_attr sPat [(sign_extend "s") (zero_extend "u")]) -(define_code_attr szPat [(sign_extend "") (zero_extend "zero_")]) -(define_code_attr szIsa [(sign_extend "x") (zero_extend "z")]) - -(define_code_iterator sz_xtnd [ sign_extend zero_extend]) -(define_code_iterator any_cond [eq ne gt gtu lt ltu ge geu le leu]) -(define_code_iterator plusminus [plus minus]) - -(define_code_attr plusminus_insn [(plus "add") (minus "sub")]) -(define_code_attr plusminus_flag [(plus "PLUS") (minus "MINUS")]) -(define_code_attr comm [(plus "%") (minus "")]) - -(define_code_iterator any_logic [and ior xor]) -(define_code_attr logic [(and "and") (ior "or") (xor "xor")]) -(define_code_attr any_logic_insn [(and "and") (ior "ior") (xor "xor")]) -(define_code_attr any_logic_flag [(and "AND") (ior "IOR") (xor "XOR")]) - -(define_mode_iterator QH [QI HI]) -(define_mode_attr qh [(QI "qi") (HI "hi")]) -(define_mode_attr QHsz [(QI "2,2,2") (HI "2,2,4")]) -(define_mode_attr QHsuffix [(QI "b") (HI "w")]) - - -;; Function Prologue and Epilogue -(define_expand "prologue" - [(const_int 0)] - "" - { - cr16_expand_prologue (); - DONE; - } -) - -(define_insn "push_for_prologue" - [(set (reg:SI SP_REGNUM) - (minus:SI (reg:SI SP_REGNUM) - (match_operand:SI 0 "immediate_operand" "i")))] - "reload_completed" - { - return cr16_prepare_push_pop_string (0); - } - [(set_attr "length" "4")] -) - -(define_expand "epilogue" - [(return)] - "" - { - cr16_expand_epilogue (); - DONE; - } -) - -(define_insn "pop_and_popret_return" - [(set (reg:SI SP_REGNUM) - (plus:SI (reg:SI SP_REGNUM) - (match_operand:SI 0 "immediate_operand" "i"))) - (use (reg:SI RA_REGNUM)) - (return)] - "reload_completed" - { - return cr16_prepare_push_pop_string (1); - } - [(set_attr "length" "4")] -) - -(define_insn "popret_RA_return" - [(use (reg:SI RA_REGNUM)) - (return)] - "reload_completed" - "popret\tra" - [(set_attr "length" "2")] -) - -;; Arithmetic Instruction Patterns - -;; Addition-Subtraction "adddi3/subdi3" insns. -(define_insn "<plusminus_insn>di3" - [(set (match_operand:DI 0 "register_operand" "=r") - (plusminus:DI (match_operand:DI 1 "register_operand" "<comm>0") - (match_operand:DI 2 "register_operand" "r")))] - "" - { - return cr16_emit_add_sub_di (operands, <plusminus_flag>); - }) - -(define_insn "addsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0") - (match_operand:SI 2 "reg_si_int_operand" "r,M,N,O,i")))] - "" - "addd\t%2, %0" - [(set_attr "length" "2,2,4,4,6")] -) - -;; Addition-Subtraction "addhi3/subhi3" insns. -(define_insn "<plusminus_insn>hi3" - [(set (match_operand:HI 0 "register_operand" "=c,c,c") - (plusminus:HI (match_operand:HI 1 "register_operand" "<comm>0,0,0") - (match_operand:HI 2 "reg_hi_int_operand" "c,M,N")))] - "" - "<plusminus_insn>w\t%2, %0" - [(set_attr "length" "2,2,4")] -) - -;; Addition-Subtraction "addqi3/subqi3" insns. -(define_insn "<plusminus_insn>qi3" - [(set (match_operand:QI 0 "register_operand" "=c,c") - (plusminus:QI (match_operand:QI 1 "register_operand" "<comm>0,0") - (match_operand:QI 2 "reg_qi_int_operand" "c,M")))] - "" - "<plusminus_insn>b\t%2, %0" - [(set_attr "length" "2,2")] -) - -;; Subtract Instruction -(define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (minus:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:SI 2 "reg_si_int_operand" "r,i")))] - "" - "subd\t%2, %0" - [(set_attr "length" "4,6")] -) - -;; Multiply and Accumulate Instructions "smachisi3/umachisi3" -(define_insn "<sPat>maddhisi4" - [(set (match_operand:SI 0 "register_operand" "=r") - (plus:SI - (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")) - (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r"))) - (match_operand:SI 3 "register_operand" "0")))] - "TARGET_MAC" - "mac<sPat>w\t%1, %2, %0" - [(set_attr "length" "2")] -) - -;; Multiply Instructions -(define_insn "mulhi3" - [(set (match_operand:HI 0 "register_operand" "=c,c,c") - (mult:HI (match_operand:HI 1 "register_operand" "%0,0,0") - (match_operand:HI 2 "reg_or_int_operand" "c,M,N")))] - "" - "mulw\t%2, %0" - [(set_attr "length" "2,2,4")] -) - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=c") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (sign_extend:HI (match_operand:QI 2 "register_operand" "c"))))] - "" - "mulsb\t%2, %0" - [(set_attr "length" "2")] -) - -;; Bit Set/Clear Instructions -(define_expand "insv" - [(set (zero_extract (match_operand 0 "memory_operand" "") - (match_operand 1 "immediate_operand" "") - (match_operand 2 "immediate_operand" "")) - (match_operand 3 "immediate_operand" ""))] - "TARGET_BIT_OPS" - { - if (INTVAL (operands[1]) != 1) - FAIL; - if (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 15) - FAIL; - if (INTVAL (operands[3]) == 1) - { - if (GET_MODE (operands[0]) == QImode) - { - emit_insn (gen_set_bitqi (operands[0], operands[2])); - DONE; - } - else if (GET_MODE (operands[0]) == HImode) - { - emit_insn (gen_set_bithi (operands[0], operands[2])); - DONE; - } - } - if (INTVAL (operands[3]) == 0) - { - if (GET_MODE (operands[0]) == QImode) - { - emit_insn (gen_clr_bitqi (operands[0], operands[2])); - DONE; - } - else if (GET_MODE (operands[0]) == HImode) - { - emit_insn (gen_clr_bithi (operands[0], operands[2])); - DONE; - } - } - } -) - -(define_insn "set_bit<mode>" - [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m") - (const_int 1) - (match_operand 1 "immediate_operand" "i")) - (const_int 1))] - "TARGET_BIT_OPS" - "sbit<tIsa>\t%1,%0" - [(set_attr "length" "2")] -) - -(define_insn "clr_bit<mode>" - [(set (zero_extract:SHORT (match_operand:SHORT 0 "memory_operand" "+m") - (const_int 1) - (match_operand 1 "immediate_operand" "i")) - (const_int 0))] - "TARGET_BIT_OPS" - "cbit<tIsa>\t%1,%0" - [(set_attr "length" "2")] -) - -(define_insn "set_bit<mode>_mem" - [(set (match_operand:SHORT 0 "bit_operand" "=m") - (ior:SHORT (match_dup 0) - (match_operand:SHORT 1 "one_bit_operand" "i")) - )] - "TARGET_BIT_OPS" - "sbit<tIsa>\t$%s1,%0" - [(set_attr "length" "2")] -) - -(define_insn "clear_bit<mode>_mem" - [(set (match_operand:SHORT 0 "bit_operand" "=m") - (and:SHORT (match_dup 0) - (match_operand:SHORT 1 "rev_one_bit_operand" "i")) - )] - "TARGET_BIT_OPS" - "cbit<tIsa>\t$%r1,%0" - [(set_attr "length" "2")] -) - -;; Logical Instructions - and/ior/xor "anddi3/iordi3/xordi3" -(define_insn "<any_logic_insn>di3" - [(set (match_operand:DI 0 "register_operand" "=r") - (any_logic:DI (match_operand:DI 1 "register_operand" "%0") - (match_operand:DI 2 "register_operand" "r")))] - "" - { - return cr16_emit_logical_di (operands, <any_logic_flag>); - }) - -; Logical and/ior/xor "andsi3/iorsi3/xorsi3" -(define_insn "<any_logic_insn>si3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (any_logic:SI (match_operand:SI 1 "register_operand" "%0,0,0,0") - (match_operand:SI 2 "reg_si_int_operand" "r,M,N,i")))] - "" - "<logic>d\t%2, %0" - [(set_attr "length" "2,2,4,6")] -) - -; Logical and/ior/xor in HImode "andhi3/iorhi3/xorhi3" -; Logical and/ior/xor in QImode "andqi3/iorqi3/xorqi3" -(define_insn "<any_logic_insn><qh>3" - [(set (match_operand:QH 0 "register_operand" "=c,c,c") - (any_logic:QH (match_operand:QH 1 "register_operand" "%0,0,0") - (match_operand:QH 2 "reg_hi_int_operand" "c,M,N")))] - "" - "<logic><QHsuffix>\t%2, %0" - [(set_attr "length" "<QHsz>")] -) - -;; Sign and Zero Extend Instructions -(define_insn "<szPat>extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))] - "" - "mov<szIsa>w\t%1, %0" - [(set_attr "length" "4")] -) - -(define_insn "<szPat>extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))] - "" - "mov<szIsa>b\t%1, %0" - [(set_attr "length" "4")] -) - -;; One's Complement -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (match_operand:DI 1 "register_operand" "0")))] - "" - { - rtx xoperand ; - int reg0 = REGNO (operands[0]); - - xoperand = gen_rtx_REG (SImode, reg0 + 2); - output_asm_insn ("xord\t$-1, %0", operands); - output_asm_insn ("xord\t$-1, %0", &xoperand); - return "" ; - } - [(set_attr "length" "12")] -) - -(define_insn "one_cmpl<mode>2" - [(set (match_operand:CR16IM 0 "register_operand" "=r") - (not:CR16IM (match_operand:CR16IM 1 "register_operand" "0")))] - "" - "xor<tIsa>\t$-1, %0" - [(set_attr "length" "2")] -) - -;; Arithmetic Left and Right Shift Instructions -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "register_operand" "=c,c") - (ashift:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "c,I")))] - "" - "ashub\t%2, %0" - [(set_attr "length" "2,2")] -) - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=c,c") - (ashift:HI (match_operand:HI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "c,J")))] - "" - "ashuw\t%2, %0" - [(set_attr "length" "2,2")] -) - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "register_operand" "0,0") - (match_operand:QI 2 "nonmemory_operand" "r,K")))] - "" - "ashud\t%2, %0" - [(set_attr "length" "2,2")] -) - -(define_expand "ashr<mode>3" - [(set (match_operand:CR16IM 0 "register_operand" "") - (ashiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - { - if (GET_CODE (operands[2]) == CONST_INT) - { - /* If the constant is not in range, try placing it in a reg */ - if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>)) - operands[2] = copy_to_mode_reg(QImode, operands[2]); - } - - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); - } -) - -(define_insn "ashrqi3_imm_insn" - [(set (match_operand:QI 0 "register_operand" "=c") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "shift_qi_imm_operand" "i")))] - "" - "ashub\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "ashrhi3_imm_insn" - [(set (match_operand:HI 0 "register_operand" "=c") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "shift_hi_imm_operand" "i")))] - "" - "ashuw\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "ashrsi3_imm_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "shift_si_imm_operand" "i")))] - "" - "ashud\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "ashrqi3_neg_insn" - [(set (match_operand:QI 0 "register_operand" "=c") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "c"))))] - "" - "ashub\t%2,%0" - [(set_attr "length" "2")] -) - -(define_insn "ashrhi3_neg_insn" - [(set (match_operand:HI 0 "register_operand" "=c") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "c"))))] - "" - "ashuw\t%2,%0" - [(set_attr "length" "2")] -) - -(define_insn "ashrdi3_neg_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "ashud\t%2,%0" - [(set_attr "length" "2")] -) - -(define_expand "lshr<mode>3" - [(set (match_operand:CR16IM 0 "register_operand" "") - (lshiftrt:CR16IM (match_operand:CR16IM 1 "register_operand" "") - (match_operand:QI 2 "reg_or_int_operand" "")))] - "" - { - if (GET_CODE (operands[2]) == CONST_INT) - { - /* If the constant is not in range, try placing it in a reg */ - if (!UNSIGNED_INT_FITS_N_BITS(INTVAL (operands[2]),<shImmBits>)) - operands[2] = copy_to_mode_reg(QImode, operands[2]); - } - - if (GET_CODE (operands[2]) != CONST_INT) - operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2])); - } -) - -(define_insn "lshrqi3_imm_insn" - [(set (match_operand:QI 0 "register_operand" "=c") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "shift_qi_operand" "Q")))] - "" - "lshb\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "lshrhi3_imm_insn" - [(set (match_operand:HI 0 "register_operand" "=c") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "shift_hi_operand" "R")))] - "" - "lshw\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "lshrsi3_imm_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "shift_si_operand" "S")))] - "" - "lshd\t$%n2, %0" - [(set_attr "length" "2")] -) - -(define_insn "lshrqi3_neg_insn" - [(set (match_operand:QI 0 "register_operand" "=c") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "c"))))] - "" - "lshb\t%2,%0" - [(set_attr "length" "2")] -) - -(define_insn "lshrhi3_neg_insn" - [(set (match_operand:HI 0 "register_operand" "=c") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "c"))))] - "" - "lshw\t%2,%0" - [(set_attr "length" "2")] -) - -(define_insn "lshrsi3_neg_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (neg:QI (match_operand:QI 2 "register_operand" "r"))))] - "" - "lshd\t%2,%0" - [(set_attr "length" "2")] -) - -;; Move Instructions - -;; Move any non-immediate operand 0 to a general operand 1. -;; This applies only before starting the reload process -;; Operand 0 is not a register operand of type mode MODE -;; If Operand 0 is a push operand of type mode MODE -;; then, if Operand 1 is a non-SP register -;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1) -;; endif -;; else -;; if Operand 1 is either register or 4-bit immediate constant -;; then, Operand 1 = copy_to_mode_reg (<MODE>mode, Operand 1) -;; endif -;; endif -;; -;; What does copy_to_mode_reg (mode, rtx val) do? -;; Copy the value into new temp reg and return the reg where the -;; mode of the new reg is always mode MODE when value is constant -;; -;; Why should copy_to_mode_reg be called? -;; All sorts of move are nor supported by CR16. Therefore, -;; when unsupported move is encountered, the additional instructions -;; will be introduced for the purpose. -;; -;; A new move insn is inserted for Op 1 when one of the following -;; conditions is met. -;; Case 1: Op 0 is push_operand -;; Op 1 is SP register -;; -;; Case 2: Op 0 is not push_operand -;; Op 1 is neither register nor unsigned 4-bit immediate - -(define_expand "mov<mode>" - [(set (match_operand:ALLMTD 0 "nonimmediate_operand" "") - (match_operand:ALLMTD 1 "general_operand" ""))] - "" - { - if (!(reload_in_progress || reload_completed)) - { - /* Only if Op0 is a register operand. */ - if (!register_operand (operands[0], <MODE>mode)) - { - if (push_operand (operands[0], <MODE>mode)) - { - /* Use copy_to_mode_reg only if the register needs - to be pushed is SP as CR16 does not support pushing SP. */ - if (!nosp_reg_operand (operands[1], <MODE>mode)) - operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); - } - else - { - /* Use copy_to_mode_reg if op1 is not register operand - subject to conditions inside. */ - if (!register_operand (operands[1], <MODE>mode)) - { - /* CR16 does not support moving immediate to SI or SF - type memory. */ - if (<MODE>mode == SImode || <MODE>mode == SFmode || - <MODE>mode == DImode || <MODE>mode == DFmode) - operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); - else - /* moving imm4 is supported by CR16 instruction. */ - if (!u4bits_operand (operands[1], <MODE>mode)) - operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]); - } - } - } - - /* If operand-1 is a symbol, convert it into a BRO or GOT Format. */ - if (flag_pic && ! legitimate_pic_operand_p (operands[1])) - { - operands[1] = legitimize_pic_address (operands[1], <MODE>mode, 0); - } - } - } -) - -; ALLMT : QI,HI,SI,SF -; pushCnstr : Push constraints -; QI : X -; HI,SI,SF,DI,DF : < -; b : All non-sp registers -; tpush : Push count -; QI,HI : 1 -; SI,SF : 2 -; DI,DF : 4 -(define_insn "push<mode>_internal" - [(set (match_operand:ALLMTD 0 "push_operand" "=<pushCnstr>") - (match_operand:ALLMTD 1 "nosp_reg_operand" "b"))] - "" - "push\t$<tpush>,%p1" - [(set_attr "length" "2")] -) - -; (DI, DF) move -(define_insn "*mov<mode>_double" - [(set (match_operand:DOUBLE 0 "nonimmediate_operand" "=r, r, r, m") - (match_operand:DOUBLE 1 "general_operand" "r, <iFD>, m, r"))] - "register_operand (operands[0], DImode) - || register_operand (operands[0], DFmode) - || register_operand (operands[1], DImode) - || register_operand (operands[1], DFmode)" - { - if (which_alternative == 0) { - rtx xoperands[2]; - int reg0 = REGNO (operands[0]); - int reg1 = REGNO (operands[1]); - - xoperands[0] = gen_rtx_REG (SImode, reg0 + 2); - xoperands[1] = gen_rtx_REG (SImode, reg1 + 2); - if ((reg1 + 2) != reg0) - { - output_asm_insn ("movd\t%1, %0", operands); - output_asm_insn ("movd\t%1, %0", xoperands); - } - else - { - output_asm_insn ("movd\t%1, %0", xoperands); - output_asm_insn ("movd\t%1, %0", operands); - }} - - else if (which_alternative == 1) { - rtx lo_operands[2]; - rtx hi_operands[2]; - - lo_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - hi_operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2); - lo_operands[1] = simplify_gen_subreg (SImode, operands[1], - VOIDmode == GET_MODE (operands[1]) - ? DImode : GET_MODE (operands[1]), 0); - hi_operands[1] = simplify_gen_subreg (SImode, operands[1], - VOIDmode == GET_MODE (operands[1]) - ? DImode : GET_MODE (operands[1]), 4); - output_asm_insn ("movd\t%1, %0", lo_operands); - output_asm_insn ("movd\t%1, %0", hi_operands);} - - else if (which_alternative == 2) { - rtx xoperands[2]; - int reg0 = REGNO (operands[0]), reg1 = -2; - rtx addr; - - if (MEM_P (operands[1])) - addr = XEXP (operands[1], 0); - else - addr = NULL_RTX; - switch (GET_CODE (addr)) - { - case REG: - case SUBREG: - reg1 = REGNO (addr); - break; - case PLUS: - switch (GET_CODE (XEXP (addr, 0))) { - case REG: - case SUBREG: - reg1 = REGNO (XEXP (addr, 0)); - break; - case PLUS: - reg1 = REGNO (XEXP (XEXP (addr, 0), 0)); - break; - default: - inform (DECL_SOURCE_LOCATION (cfun->decl), "unexpected expression; addr:"); - debug_rtx (addr); - inform (DECL_SOURCE_LOCATION (cfun->decl), "operands[1]:"); - debug_rtx (operands[1]); - inform (DECL_SOURCE_LOCATION (cfun->decl), "generated code might now work\n"); - break;} - break; - default: - break; - } - - xoperands[0] = gen_rtx_REG (SImode, reg0 + 2); - xoperands[1] = offset_address (operands[1], GEN_INT (4), 2); - gcc_assert ((reg0 + 1) != reg1); - if (reg0 != reg1 && (reg1 + 1) != reg0) - { - output_asm_insn ("loadd\t%1, %0", operands); - output_asm_insn ("loadd\t%1, %0", xoperands); - } - else - { - output_asm_insn ("loadd\t%1, %0", xoperands); - output_asm_insn ("loadd\t%1, %0", operands); - }} - else - { - rtx xoperands[2]; - xoperands[0] = offset_address (operands[0], GEN_INT (4), 2); - xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2); - output_asm_insn ("stord\t%1, %0", operands); - output_asm_insn ("stord\t%1, %0", xoperands); - } - return ""; - } - [(set_attr "length" "4, <lImmArithD>, <lImmArithD>, <lImmArithD>")] -) - -; All long (SI, SF) register move, load and store operations -; The print_operand will take care of printing the register pair -; when mode is SI/SF and register is in SHORT_REGS -(define_insn "*mov<mode>_long" - [(set (match_operand:LONG 0 "nonimmediate_operand" "=r, r, r, m") - (match_operand:LONG 1 "general_operand" "r, <iF>, m, r"))] - "register_operand (operands[0], <MODE>mode) - || register_operand (operands[1], <MODE>mode)" - "@ - mov<tIsa>\t%1, %0 - mov<tIsa>\t%1, %0 - load<tIsa>\t%1, %0 - stor<tIsa>\t%1, %0" - [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>")] -) - -;; All short (QI, HI) register move, load and store operations -(define_insn "*mov<mode>_short" - [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r, r, r, m, m") - (match_operand:SHORT 1 "general_operand" "r, <iF>, m, r, <LL>"))] - "(register_operand (operands[0], <MODE>mode)) - || (store_operand (operands[0], <MODE>mode) - && (register_operand (operands[1], <MODE>mode) - || u4bits_operand (operands[1], <MODE>mode)))" - "@ - mov<tIsa>\t%1, %0 - mov<tIsa>\t%1, %0 - load<tIsa>\t%1, %0 - stor<tIsa>\t%1, %0 - stor<tIsa>\t%1, %0" - [(set_attr "length" "2,<lImmArith>,<lImmArith>,<lImmArith>,<lImmArith>")] -) - -;; Compare Instructions -; Instruction generated compares the operands in reverse order -; Therefore, while printing the asm, the reverse of the -; compare condition shall be printed. -(define_insn "cbranch<mode>4" - [(set (pc) - (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:CR16IM 1 "register_operand" "r,r") - (match_operand:CR16IM 2 "nonmemory_operand" "r,n")]) - (label_ref (match_operand 3 "" "")) - (pc))) - (clobber (cc0))] - "" - "cmp<tIsa>\t%2, %1\;b%d0\t%l3" - [(set_attr "length" "6,6")] -) - -(define_expand "cmp<mode>" - [(parallel [(set (cc0) - (compare (match_operand:CR16IM 0 "register_operand" "") - (match_operand:CR16IM 1 "nonmemory_operand" ""))) - (clobber (match_scratch:HI 2 "=r"))] ) ] - "" - "") - -;; Scond Instructions -(define_expand "cstore<mode>4" - [(set (cc0) - (compare (match_operand:CR16IM 2 "register_operand" "") - (match_operand:CR16IM 3 "nonmemory_operand" ""))) - (set (match_operand:HI 0 "register_operand") - (match_operator:HI 1 "ordered_comparison_operator" - [(cc0) (const_int 0)]))] - "" - "" -) - -(define_insn "*cmp<mode>_insn" - [(set (cc0) - (compare (match_operand:CR16IM 0 "register_operand" "r,r") - (match_operand:CR16IM 1 "nonmemory_operand" "r,n")))] - "" - "cmp<tIsa>\t%1, %0" - [(set_attr "length" "2,4")] -) - -(define_insn "sCOND_internal" - [(set (match_operand:HI 0 "register_operand" "=r") - (match_operator:HI 1 "ordered_comparison_operator" - [(cc0) (const_int 0)]))] - "" - "s%d1\t%0" - [(set_attr "length" "2")] -) - -;; Jumps and Branches -(define_insn "indirect_jump_return" - [(set (pc) - (reg:SI RA_REGNUM)) - (return)] - "reload_completed" - "jump\t (ra)" - [(set_attr "length" "2")] -) - -(define_insn "jump_return" - [(unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR) - (return)] - "reload_completed" - "jump\t(ra)" - [(set_attr "length" "2")] -) - -(define_insn "indirect_jump" - [(set (pc) - (match_operand:SI 0 "reg_or_sym_operand" "r,i"))] - "" - "@ - jump\t%0 - br\t%a0" - [(set_attr "length" "2,6")] -) - -(define_insn "interrupt_return" - [(unspec_volatile [(const_int 0)] 0) - (return)] - "" - { - return cr16_prepare_push_pop_string (1); - } - [(set_attr "length" "14")] -) - -(define_insn "jump_to_imm" - [(set (pc) - (match_operand 0 "jump_imm_operand" "i"))] - "" - "br\t%c0" - [(set_attr "length" "6")] -) - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "br\t%l0" - [(set_attr "length" "6")] -) - -;; Table Jump -(define_insn "tablejump" - [(set (pc) - (match_operand:SI 0 "register_operand" "r")) - (use (label_ref:SI (match_operand 1 "" "")))] - "!flag_pic" - "jump\t%0" - [(set_attr "length" "2")] -) - -;; Call Instructions -(define_expand "call" - [(call (match_operand:QI 0 "memory_operand" "") - (match_operand 1 "" ""))] - "" - { - if (flag_pic && ! legitimate_pic_operand_p (operands[0])) - { - operands[0] = gen_const_mem (QImode, - legitimize_pic_address (XEXP (operands[0], 0), Pmode, 0)); - emit_call_insn (gen_cr16_call (operands[0], operands[1])); - } - else - emit_call_insn (gen_cr16_call (operands[0], operands[1])); - DONE; - } -) - -(define_expand "cr16_call" - [(parallel - [(call (match_operand:QI 0 "memory_operand" "") - (match_operand 1 "" "")) - (clobber (reg:SI RA_REGNUM))])] - "" - "" -) - -(define_insn "cr16_call_insn_branch_pic" - [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i")) - (match_operand 1 "" "")) - (clobber (match_operand:SI 2 "register_operand" "+r"))] - "flag_pic == FAR_PIC" - { - if (GET_CODE (operands[0]) != CONST_INT) - return "loadd\t%g0, %2 \n\tjal %2"; - else - return "jal %2"; - } - [(set_attr "length" "8")] -) - -(define_insn "cr16_call_insn_branch" - [(call (mem:QI (match_operand:SI 0 "call_imm_operand" "i")) - (match_operand 1 "" "")) - (clobber (match_operand:SI 2 "register_operand" "+r"))] - "flag_pic == 0 || flag_pic == NEAR_PIC" - { - /* Print the immediate address for bal - 'b' is used instead of 'a' to avoid compiler calling - the GO_IF_LEGITIMATE_ADDRESS which cannot - perform checks on const_int code addresses as it - assumes all const_int are data addresses. - */ - if (GET_CODE (operands[0]) != CONST_INT) - return "bal (ra), %a0"; - else - operands[4] = GEN_INT ((INTVAL (operands[0]))>>1); - return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)"; - } - [(set_attr "length" "6")] -) - -(define_insn "cr16_call_insn_jump" - [(call (mem:QI (match_operand:SI 0 "register_operand" "r")) - (match_operand 1 "" "")) - (clobber (match_operand:SI 2 "register_operand" "+r"))] - "" - "jal\t%0" - [(set_attr "length" "2")] -) - -;; Call Value Instructions - -(define_expand "call_value" - [(set (match_operand 0 "general_operand" "") - (call (match_operand:QI 1 "memory_operand" "") - (match_operand 2 "" "")))] - "" - { - if (flag_pic && !legitimate_pic_operand_p (operands[1])) - { - operands[1] = gen_const_mem (QImode, - legitimize_pic_address (XEXP (operands[1], 0), Pmode, 0)); - emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2])); - } - else - emit_call_insn (gen_cr16_call_value (operands[0], operands[1], operands[2])); - DONE; - } -) - -(define_expand "cr16_call_value" - [(parallel - [(set (match_operand 0 "general_operand" "") - (call (match_operand 1 "memory_operand" "") - (match_operand 2 "" ""))) - (clobber (reg:SI RA_REGNUM))])] - "" - "" -) - -(define_insn "cr16_call_value_insn_branch_pic" - [(set (match_operand 0 "" "=g") - (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i")) - (match_operand 2 "" ""))) - (clobber (match_operand:SI 3 "register_operand" "+r"))] - "flag_pic == FAR_PIC" - { - if (GET_CODE (operands[1]) != CONST_INT) - return "loadd\t%g1, %3 \n\tjal %3"; - else - return "jal %3"; - } - [(set_attr "length" "8")] -) - -(define_insn "cr16_call_value_insn_branch" - [(set (match_operand 0 "" "=g") - (call (mem:QI (match_operand:SI 1 "call_imm_operand" "i")) - (match_operand 2 "" ""))) - (clobber (match_operand:SI 3 "register_operand" "+r"))] - "flag_pic == 0 || flag_pic == NEAR_PIC" - { - /* Print the immediate address for bal - 'b' is used instead of 'a' to avoid compiler calling - the GO_IF_LEGITIMATE_ADDRESS which cannot - perform checks on const_int code addresses as it - assumes all const_int are data addresses. - */ - if (GET_CODE (operands[1]) != CONST_INT) - return "bal (ra), %a1"; - else - { - operands[4] = GEN_INT ((INTVAL (operands[1]))>>1); - return "movd\t%g4,\t(r1,r0)\n\tjal\t(r1,r0)"; - } - } - [(set_attr "length" "6")] -) - - -(define_insn "cr16_call_value_insn_jump" - [(set (match_operand 0 "" "=g") - (call (mem:QI (match_operand:SI 1 "register_operand" "r")) - (match_operand 2 "" ""))) - (clobber (match_operand:SI 3 "register_operand" "+r"))] - "" - "jal\t%1" - [(set_attr "length" "2")] -) - - -;; Nop -(define_insn "nop" - [(const_int 0)] - "" - "nop\t" -) - -;; PIC -/* When generating pic, we need to load the symbol offset into a register. - So that the optimizer does not confuse this with a normal symbol load - we use an unspec. The offset will be loaded from a constant pool entry, - since that is the only type of relocation we can use. */ - -(define_insn "unspec_bro_addr" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_ADDR))] - "" - "movd \t%f1, %0" - [(set_attr "length" "4")] -) - -(define_insn "unspec_got_addr" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))] - "" - "loadd \t%g1, %0" - [(set_attr "length" "6")] -) diff --git a/gcc/config/cr16/cr16.opt b/gcc/config/cr16/cr16.opt deleted file mode 100644 index 8d7da69..0000000 --- a/gcc/config/cr16/cr16.opt +++ /dev/null @@ -1,51 +0,0 @@ -; Options for the National Semiconductor CR16 port of the compiler. -; Copyright (C) 2012-2022 Free Software Foundation, Inc. -; Contributed by KPIT Cummins Infosystems Limited. -; -; This file is part of GCC. -; -; GCC is free software; you can redistribute it and/or modify it -; under the terms of the GNU General Public License as published -; by the Free Software Foundation; either version 3, or (at your -; option) any later version. -; -; GCC is distributed in the hope that it will be useful, but WITHOUT -; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -; License for more details. -; -; You should have received a copy of the GNU General Public License -; along with GCC; see the file COPYING3. If not see -; <http://www.gnu.org/licenses/>. - -msim -Target -Use simulator runtime. - -mbit-ops -Target Mask(BIT_OPS) -Generate SBIT, CBIT instructions. - -mmac -Target Mask(MAC) -Support multiply accumulate instructions. - -mdebug-addr -Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented - -mdata-model= -Target RejectNegative JoinedOrMissing Var(cr16_data_model) -Treat data references as near, far or medium. medium is default. - -mcr16c -Target RejectNegative Mask(CR16C) -Generate code for CR16C architecture. - -mcr16cplus -Target RejectNegative InverseMask(CR16C,CR16CP) -Generate code for CR16C+ architecture (Default). - -mint32 -Target RejectNegative Mask(INT32) -Treat integers as 32-bit. - diff --git a/gcc/config/cr16/predicates.md b/gcc/config/cr16/predicates.md deleted file mode 100644 index d8789f5a..0000000 --- a/gcc/config/cr16/predicates.md +++ /dev/null @@ -1,225 +0,0 @@ -;; Predicates of machine description for CR16. -;; Copyright (C) 2012-2022 Free Software Foundation, Inc. -;; Contributed by KPIT Cummins Infosystems Limited. -;; -;; This file is part of GCC. -;; -;; GCC is free software; you can redistribute it and/or modify it -;; under the terms of the GNU General Public License as published -;; by the Free Software Foundation; either version 3, or (at your -;; option) any later version. -;; -;; GCC is distributed in the hope that it will be useful, but WITHOUT -;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -;; License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with GCC; see the file COPYING3. If not see -;; <http://www.gnu.org/licenses/>. - -;; Predicates - -;; Predicates for sbit/cbit instructions -;; bit operand used for the generation of bit insn generation -(define_predicate "bit_operand" - (match_code "mem") -{ - return ((GET_CODE (op) == MEM && OK_FOR_Z (op))); -}) - -;; Unsigned 4-bits constant int or double value. -(define_predicate "u4bits_operand" - (match_code "const_int,const_double") -{ - if (GET_CODE (op) == CONST_DOUBLE) - return cr16_const_double_ok (op); - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0; -}) - -;; Operand is a constant integer where -;; only one bit is set to 1. -(define_predicate "one_bit_operand" - (match_code "const_int") -{ - unsigned int val; - - val = INTVAL (op); - if (mode == QImode) - val &= 0xff; - else if (mode == HImode) - val &= 0xffff; - else - gcc_unreachable(); - - if (val != 0) - return (val & (val - 1)) == 0; /* true if only one bit is set. */ - else - return 0; -}) - -;; Operand is a constant integer where -;; only one bit is set to 0. -(define_predicate "rev_one_bit_operand" - (match_code "const_int") -{ - unsigned int val; - - val = ~INTVAL (op); /* Invert and use. */ - if (mode == QImode) - val &= 0xff; - else if (mode == HImode) - val &= 0xffff; - else - gcc_unreachable(); - - if (val != 0) - return (val & (val - 1)) == 0; /* true if only one bit is set. */ - else - return 0; -}) - -;; Predicates for shift instructions -;; Immediate operand predicate for count in shift operations. -;; Immediate shall be 3-bits in case operand to be operated on -;; is a qi mode operand. -(define_predicate "shift_qi_imm_operand" - (match_code "const_int") -{ - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 3)) ? 1 : 0; -}) - -;; Immediate shall be 4-bits in case operand to be operated on -;; is a hi mode operand. -(define_predicate "shift_hi_imm_operand" - (match_code "const_int") -{ - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 4)) ? 1 : 0; -}) - -;; Immediate shall be 3-bits in case operand to be operated on -;; is a si mode operand. -(define_predicate "shift_si_imm_operand" - (match_code "const_int") -{ - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 5)) ? 1 : 0; -}) - -;; Predicates for jump/call instructions -;; Jump immediate cannot be more than 24-bits -(define_predicate "jump_imm_operand" - (match_code "const_int") -{ - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0; -}) - -;; Call immediate cannot be more than 24-bits -(define_predicate "call_imm_operand" - (match_operand 0 "immediate_operand") -{ - if (GET_CODE (op) != CONST_INT) return 1; - return (UNSIGNED_INT_FITS_N_BITS(INTVAL (op), 24)) ? 1 : 0; -}) - -;; Operand is register or 4-bit immediate operand -(define_predicate "reg_or_u4bits_operand" - (ior (match_operand 0 "u4bits_operand") - (match_operand 0 "register_operand"))) - -;; Operand is a register or symbol reference -(define_predicate "reg_or_sym_operand" - (ior (match_code "symbol_ref") - (match_operand 0 "register_operand"))) - -;; Operand is a non stack pointer register -(define_predicate "nosp_reg_operand" - (and (match_operand 0 "register_operand") - (match_test "REGNO (op) != SP_REGNUM"))) - -(define_predicate "hard_reg_operand" - (and (match_operand 0 "register_operand") - (match_test "REGNO (op) <= 15"))) - -;; Operand is a memory reference and -;; not a push operand. -(define_predicate "store_operand" - (and (match_operand 0 "memory_operand") - (not (match_operand 0 "push_operand")))) - -;; Helper predicate -(define_predicate "reg_or_int_operand" - (ior (match_code "const_int") - (match_operand 0 "register_operand"))) - -;; -;; -;; Atithmetic/logical predicates - -;; QI Helper -(define_predicate "arith_qi_operand" - (match_code "const_int") -{ - return (IN_RAN(INTVAL (op), 0, 15) && ((INTVAL (op) != 9) - || (INTVAL (op) != 11))) ? 1 : 0 ; -}) - -;;QI Reg, subreg(reg) or const_int. -(define_predicate "reg_qi_int_operand" - (ior (match_operand 0 "arith_qi_operand") - (match_operand 0 "register_operand"))) - -;; HI Helper -(define_predicate "arith_hi_operand" - (match_code "const_int") -{ - return (IN_RAN(INTVAL (op), -32768, 32768) ) ? 1 : 0 ; -}) - -;;HI Reg, subreg(reg) or const_int. -(define_predicate "reg_hi_int_operand" - (ior (match_operand 0 "arith_hi_operand") - (match_operand 0 "register_operand"))) - -;;SI Reg, subreg(reg) or const_int. -(define_predicate "reg_si_int_operand" - (ior (match_operand 0 "const_int_operand") - (match_operand 0 "register_operand"))) - -;; -;; Shift predicates - -;; QI Helper -(define_predicate "shift_qi_operand" - (match_code "const_int") -{ - return (IN_RAN(INTVAL (op), 0, 7) ) ? 1 : 0; -}) - -;;QI Reg, subreg(reg) or const_int. -(define_predicate "shift_reg_qi_int_operand" - (ior (match_operand 0 "shift_qi_operand") - (match_operand 0 "register_operand"))) - -;; HI Helper -(define_predicate "shift_hi_operand" - (match_code "const_int") -{ - return (IN_RAN(INTVAL (op), 0, 15) ) ? 1 : 0 ; -}) - -;;HI Reg, subreg(reg) or const_int. -(define_predicate "shift_reg_hi_int_operand" - (ior (match_operand 0 "shift_hi_operand") - (match_operand 0 "register_operand"))) - -;; SI Helper -(define_predicate "shift_si_operand" - (match_code "const_int") -{ - return (IN_RAN(INTVAL (op), 0, 31) ) ? 1 : 0; -}) - -;;SI Reg, subreg(reg) or const_int. -(define_predicate "shift_reg_si_int_operand" - (ior (match_operand 0 "shift_si_operand") - (match_operand 0 "register_operand"))) diff --git a/gcc/config/cr16/t-cr16 b/gcc/config/cr16/t-cr16 deleted file mode 100644 index 928730f..0000000 --- a/gcc/config/cr16/t-cr16 +++ /dev/null @@ -1,25 +0,0 @@ -# CR16 Target Makefile -# Copyright (C) 2012-2022 Free Software Foundation, Inc. -# Contributed by KPIT Cummins Infosystems Limited. -# -# This file is part of GCC. -# -# GCC is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published -# by the Free Software Foundation; either version 3, or (at your -# option) any later version. -# -# GCC is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -# License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GCC; see the file COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -MULTILIB_OPTIONS = fPIC mint32 -MULTILIB_DIRNAMES = far-pic int32 -MULTILIB_MATCHES = -MULTILIB_EXTRA_OPTS = mcr16cplus mdata-model=far - diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 6edfe13..16caa29 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -570,7 +570,7 @@ enum reg_class an inverse mapping from dwarf register to gcc register. There is one need in dwarf2out.cc:expand_builtin_init_dwarf_reg_sizes. Right now, I don't see that we need exact correspondence between DWARF *frame* - registers and DBX_REGISTER_NUMBER, so map them onto GCC registers. */ + registers and DEBUGGER_REGNO, so map them onto GCC registers. */ #define DWARF_FRAME_REGNUM(REG) (REG) /* Node: Stack Checking */ @@ -888,7 +888,7 @@ struct cum_args {int regs;}; /* Node: All Debuggers */ -#define DBX_REGISTER_NUMBER(REGNO) \ +#define DEBUGGER_REGNO(REGNO) \ ((REGNO) == CRIS_SRP_REGNUM ? CRIS_CANONICAL_SRP_REGNUM : \ (REGNO) == CRIS_MOF_REGNUM ? CRIS_CANONICAL_MOF_REGNUM : \ (REGNO) == CRIS_CC0_REGNUM ? CRIS_CANONICAL_CC0_REGNUM : \ diff --git a/gcc/config/csky/csky.cc b/gcc/config/csky/csky.cc index e315e09..a7dc6ce 100644 --- a/gcc/config/csky/csky.cc +++ b/gcc/config/csky/csky.cc @@ -172,7 +172,7 @@ enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] = /* Arrays that map GCC register numbers to debugger register numbers, '-1' means that is INVALID_REGNUM. TODO: which rules according to here ? */ -const int csky_dbx_regno[FIRST_PSEUDO_REGISTER] = +const int csky_debugger_regno[FIRST_PSEUDO_REGISTER] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, diff --git a/gcc/config/csky/csky.h b/gcc/config/csky/csky.h index 22b1151..37410f0 100644 --- a/gcc/config/csky/csky.h +++ b/gcc/config/csky/csky.h @@ -997,7 +997,7 @@ while (0) is different from that used in other debug info sections. Given a GCC hard register number, this macro should return the .eh_frame register number.*/ -#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) +#define DWARF_FRAME_REGNUM(REG) DEBUGGER_REGNO (REG) /* If INCOMING_RETURN_ADDR_RTX is defined & the RTL is REG, define DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM. */ @@ -1006,9 +1006,9 @@ while (0) /* Use r0 and r1 to pass exception handling information. */ #define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? N : INVALID_REGNUM) -/* How to renumber registers for dbx and gdb. */ -extern const int csky_dbx_regno[]; -#define DBX_REGISTER_NUMBER(REGNO) ((unsigned int) csky_dbx_regno[REGNO]) +/* How to renumber registers for gdb. */ +extern const int csky_debugger_regno[]; +#define DEBUGGER_REGNO(REGNO) ((unsigned int) csky_debugger_regno[REGNO]) /****************************************************************** diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index c5e1ba8..d1b4f27 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -396,10 +396,10 @@ extern GTY(()) int darwin_ms_struct; #define DSYMUTIL_SPEC \ "%{!c:%{!E:%{!S:%{!r:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*:\ - %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%:debug-level-gt(0): -idsym \ + %{g*:%{!gctf:%{!gbtf:%{%:debug-level-gt(0): -idsym \ %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\ .f95|.f03|.f77|.for|.F|.F90|.F95|.F03|.d: -dsym }\ - }}}}}\ + }}}}\ }}}}}}}}" #define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC @@ -583,14 +583,7 @@ extern GTY(()) int darwin_ms_struct; "%{static} -arch %(darwin_arch) " \ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC -#ifdef HAVE_AS_STABS_DIRECTIVE -/* We only pass a debug option to the assembler if that supports stabs, since - dwarf is not uniformly supported in the assemblers. */ -#define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):%{!gdwarf*:--gstabs}}}" -#else #define ASM_DEBUG_SPEC "" -#endif - #undef ASM_DEBUG_OPTION_SPEC #define ASM_DEBUG_OPTION_SPEC "" @@ -604,10 +597,6 @@ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC #define DWARF2_DEBUGGING_INFO 1 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -#ifdef HAVE_AS_STABS_DIRECTIVE -#define DBX_DEBUGGING_INFO 1 -#endif - #define DEBUG_FRAME_SECTION "__DWARF,__debug_frame,regular,debug" #define DEBUG_INFO_SECTION "__DWARF,__debug_info,regular,debug" #define DEBUG_ABBREV_SECTION "__DWARF,__debug_abbrev,regular,debug" @@ -639,18 +628,6 @@ ASM_OPTIONS ASM_MMACOSX_VERSION_MIN_SPEC ? "__DWARF,__debug_gnu_pubt,regular,debug" \ : "__DWARF,__debug_pubtypes,regular,debug") -/* When generating stabs debugging, use N_BINCL entries. */ - -#define DBX_USE_BINCL - -/* There is no limit to the length of stabs strings. */ - -#define DBX_CONTIN_LENGTH 0 - -/* gdb needs a null N_SO at the end of each file for scattered loading. */ - -#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - /* GCC's definition of 'one_only' is the same as its definition of 'weak'. */ #define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1) diff --git a/gcc/config/dbxcoff.h b/gcc/config/dbxcoff.h deleted file mode 100644 index 02b78c6..0000000 --- a/gcc/config/dbxcoff.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Definitions needed when using stabs embedded in COFF sections. - Copyright (C) 1996-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* This file may be included by any COFF target which wishes to - support -gstabs generating stabs in sections, as produced by gas - and understood by gdb. */ - -/* Output DBX (stabs) debugging information if doing -gstabs. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Be function-relative for block and source line stab directives. */ - -#define DBX_BLOCKS_FUNCTION_RELATIVE 1 - -/* but, to make this work, functions must appear prior to line info. */ - -#define DBX_FUNCTION_FIRST - -/* Generate a blank trailing N_SO to mark the end of the .o file, since - we can't depend upon the linker to mark .o file boundaries with - embedded stabs. */ - -#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - -/* Like block addresses, stabs line numbers are relative to the - current function. */ - -#define DBX_LINES_FUNCTION_RELATIVE 1 - -/* When generating stabs debugging, use N_BINCL entries. */ - -#undef DBX_USE_BINCL -#define DBX_USE_BINCL - -/* There is no limit to the length of stabs strings. */ - -#ifndef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 0 -#endif diff --git a/gcc/config/dbxelf.h b/gcc/config/dbxelf.h deleted file mode 100644 index 4b90e95..0000000 --- a/gcc/config/dbxelf.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Definitions needed when using stabs embedded in ELF sections. - Copyright (C) 1999-2022 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/>. */ - -/* This file may be included by any ELF target which wishes to - support -gstabs generating stabs in sections, as produced by gas - and understood by gdb. */ - -#ifndef GCC_DBX_ELF_H -#define GCC_DBX_ELF_H - -/* Output DBX (stabs) debugging information if doing -gstabs. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Make LBRAC and RBRAC addresses relative to the start of the - function. The native Solaris stabs debugging format works this - way, gdb expects it, and it reduces the number of relocation - entries... */ - -#define DBX_BLOCKS_FUNCTION_RELATIVE 1 - -/* ... but, to make this work, functions must appear prior to line info. */ - -#define DBX_FUNCTION_FIRST - -/* When generating stabs debugging, use N_BINCL entries. */ - -#define DBX_USE_BINCL - -/* There is no limit to the length of stabs strings. */ - -#ifndef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 0 -#endif - -/* Like block addresses, stabs line numbers are relative to the - current function. */ - -#define DBX_LINES_FUNCTION_RELATIVE 1 - -/* Generate a blank trailing N_SO to mark the end of the .o file, since - we can't depend upon the linker to mark .o file boundaries with - embedded stabs. */ - -#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - -#endif /* ! GCC_DBX_ELF_H */ diff --git a/gcc/config/default-d.cc b/gcc/config/default-d.cc index 2d7abfc..30c359e 100644 --- a/gcc/config/default-d.cc +++ b/gcc/config/default-d.cc @@ -18,9 +18,11 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "memmodel.h" #include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" +/* Do not include tm.h or tm_p.h here; definitions needed by the target + architecture to initialize targetdm should instead be added to tm_d.h. */ + struct gcc_targetdm targetdm = TARGETDM_INITIALIZER; diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h index 8c723845a..7c6a7f3 100644 --- a/gcc/config/epiphany/epiphany.h +++ b/gcc/config/epiphany/epiphany.h @@ -795,14 +795,9 @@ do \ /* Debugging information. */ -/* Generate DBX and DWARF debugging information. */ -#define DBX_DEBUGGING_INFO 1 - +/* Generate DWARF debugging information. */ #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG - -/* Turn off splitting of long stabs. */ -#define DBX_CONTIN_LENGTH 0 /* Miscellaneous. */ diff --git a/gcc/config/freebsd-d.cc b/gcc/config/freebsd-d.cc index 9f0f5e7..189e4a6 100644 --- a/gcc/config/freebsd-d.cc +++ b/gcc/config/freebsd-d.cc @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "memmodel.h" #include "tm.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index 8cd67f7..ac5e00c 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -1737,24 +1737,24 @@ fprintf (STREAM, "\t.word .L%d\n", VALUE) /* Macros Affecting all Debug Formats. */ -/* A C expression that returns the DBX register number for the compiler +/* A C expression that returns the debugger register number for the compiler register number REGNO. In simple cases, the value of this expression may be REGNO itself. But sometimes there are some registers that the compiler - knows about and DBX does not, or vice versa. In such cases, some register - may need to have one number in the compiler and another for DBX. + knows about and debugger does not, or vice versa. In such cases, some register + may need to have one number in the compiler and another for debugger. If two registers have consecutive numbers inside GCC, and they can be used as a pair to hold a multiword value, then they *must* have consecutive - numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers + numbers after renumbering with `DEBUGGER_REGNO'. Otherwise, debuggers will be unable to access such a pair, because they expect register pairs to be consecutive in their own numbering scheme. - If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not + If you find yourself defining `DEBUGGER_REGNO' in way that does not preserve register pairs, then what you must do instead is redefine the actual register numbering scheme. This declaration is required. */ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#define DEBUGGER_REGNO(REGNO) (REGNO) #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG diff --git a/gcc/config/gcn/gcn-hsa.h b/gcc/config/gcn/gcn-hsa.h index b3079ce..85f0f2d 100644 --- a/gcc/config/gcn/gcn-hsa.h +++ b/gcc/config/gcn/gcn-hsa.h @@ -113,4 +113,4 @@ extern const char *last_arg_spec_function (int argc, const char **argv); #define DWARF2_DEBUGGING_INFO 1 #define DWARF2_ASM_LINE_DEBUG_INFO 1 #define EH_FRAME_THROUGH_COLLECT2 1 -#define DBX_REGISTER_NUMBER(REGNO) gcn_dwarf_register_number (REGNO) +#define DEBUGGER_REGNO(REGNO) gcn_dwarf_register_number (REGNO) diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index 96295e2..8266755 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -52,6 +52,7 @@ #include "rtl-iter.h" #include "dwarf2.h" #include "gimple.h" +#include "cgraph.h" /* This file should be included last. */ #include "target-def.h" @@ -4555,6 +4556,61 @@ gcn_vectorization_cost (enum vect_cost_for_stmt ARG_UNUSED (type_of_cost), return 1; } +/* Implement TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN. */ + +static int +gcn_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *ARG_UNUSED (node), + struct cgraph_simd_clone *clonei, + tree base_type, + int ARG_UNUSED (num)) +{ + unsigned int elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type)); + + if (known_eq (clonei->simdlen, 0U)) + clonei->simdlen = 64; + else if (maybe_ne (clonei->simdlen, 64U)) + { + /* Note that x86 has a similar message that is likely to trigger on + sizes that are OK for gcn; the user can't win. */ + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "unsupported simdlen %wd (amdgcn)", + clonei->simdlen.to_constant ()); + return 0; + } + + clonei->vecsize_mangle = 'n'; + clonei->vecsize_int = 0; + clonei->vecsize_float = 0; + + /* DImode ought to be more natural here, but VOIDmode produces better code, + at present, due to the shift-and-test steps not being optimized away + inside the in-branch clones. */ + clonei->mask_mode = VOIDmode; + + return 1; +} + +/* Implement TARGET_SIMD_CLONE_ADJUST. */ + +static void +gcn_simd_clone_adjust (struct cgraph_node *ARG_UNUSED (node)) +{ + /* This hook has to be defined when + TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN is defined, but we don't + need it to do anything yet. */ +} + +/* Implement TARGET_SIMD_CLONE_USABLE. */ + +static int +gcn_simd_clone_usable (struct cgraph_node *ARG_UNUSED (node)) +{ + /* We don't need to do anything here because + gcn_simd_clone_compute_vecsize_and_simdlen currently only returns one + possibility. */ + return 0; +} + /* }}} */ /* {{{ md_reorg pass. */ @@ -6454,7 +6510,7 @@ print_operand (FILE *file, rtx x, int code) gcc_unreachable (); } -/* Implement DBX_REGISTER_NUMBER macro. +/* Implement DEBUGGER_REGNO macro. Return the DWARF register number that corresponds to the GCC internal REGNO. */ @@ -6643,6 +6699,13 @@ gcn_dwarf_register_span (rtx rtl) #define TARGET_SECTION_TYPE_FLAGS gcn_section_type_flags #undef TARGET_SCALAR_MODE_SUPPORTED_P #define TARGET_SCALAR_MODE_SUPPORTED_P gcn_scalar_mode_supported_p +#undef TARGET_SIMD_CLONE_ADJUST +#define TARGET_SIMD_CLONE_ADJUST gcn_simd_clone_adjust +#undef TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN +#define TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN \ + gcn_simd_clone_compute_vecsize_and_simdlen +#undef TARGET_SIMD_CLONE_USABLE +#define TARGET_SIMD_CLONE_USABLE gcn_simd_clone_usable #undef TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \ gcn_small_register_classes_for_mode_p diff --git a/gcc/config/glibc-d.cc b/gcc/config/glibc-d.cc index f30af10..80ef27d 100644 --- a/gcc/config/glibc-d.cc +++ b/gcc/config/glibc-d.cc @@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "memmodel.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/i386/bsd.h b/gcc/config/i386/bsd.h index d19ad27..817fb6e 100644 --- a/gcc/config/i386/bsd.h +++ b/gcc/config/i386/bsd.h @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see #define ASM_LONG "\t.long\t" #define ASM_QUAD "\t.quad\t" /* Should not be used for 32bit compilation. */ -/* This was suggested, but it shouldn't be right for DBX output. -- RMS +/* This was suggested, but it shouldn't be right for debugger output. -- RMS #define ASM_OUTPUT_SOURCE_FILENAME(FILE, NAME) */ @@ -91,9 +91,3 @@ along with GCC; see the file COPYING3. If not see /* The prefix to add to user-visible assembler symbols. */ #define USER_LABEL_PREFIX "_" - -/* Sequent has some changes in the format of DBX symbols. */ -#define DBX_NO_XREFS 1 - -/* Don't split DBX symbols into continuations. */ -#define DBX_CONTIN_LENGTH 0 diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index 4515045..4007fd9 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -72,19 +72,19 @@ along with GCC; see the file COPYING3. If not see #endif -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] \ +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] \ : (dwarf_debuginfo_p () \ - ? svr4_dbx_register_map[n] : dbx_register_map[n])) + ? svr4_debugger_register_map[n] : debugger_register_map[n])) /* Map gcc register number to DWARF 2 CFA column number. For 32 bit - target, always use the svr4_dbx_register_map for DWARF .eh_frame + target, always use the svr4_debugger_register_map for DWARF .eh_frame even if we don't use DWARF .debug_frame. */ #undef DWARF_FRAME_REGNUM #define DWARF_FRAME_REGNUM(n) \ - (TARGET_64BIT ? dbx64_register_map[(n)] \ - : svr4_dbx_register_map[(n)]) + (TARGET_64BIT ? debugger64_register_map[(n)] \ + : svr4_debugger_register_map[(n)]) /* The 64-bit MS_ABI changes the set of call-used registers. */ #undef DWARF_FRAME_REGISTERS diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h index a55f6b2..5bcb711 100644 --- a/gcc/config/i386/darwin.h +++ b/gcc/config/i386/darwin.h @@ -237,11 +237,11 @@ along with GCC; see the file COPYING3. If not see /* Darwin uses the standard DWARF register numbers but the default register numbers for STABS. Fortunately for 64-bit code the default and the standard are the same. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] \ - : dwarf_debuginfo_p () ? svr4_dbx_register_map[n] \ - : dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] \ + : dwarf_debuginfo_p () ? svr4_debugger_register_map[n] \ + : debugger_register_map[n]) /* Unfortunately, the 32-bit EH information also doesn't use the standard DWARF register numbers. */ diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h index 909821e..ede50b5 100644 --- a/gcc/config/i386/djgpp.h +++ b/gcc/config/i386/djgpp.h @@ -128,8 +128,8 @@ along with GCC; see the file COPYING3. If not see #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "int" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n] +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) svr4_debugger_register_map[n] /* Default to pcc-struct-return. */ #define DEFAULT_PCC_STRUCT_RETURN 1 diff --git a/gcc/config/i386/dragonfly.h b/gcc/config/i386/dragonfly.h index 39bd280..bf8742e 100644 --- a/gcc/config/i386/dragonfly.h +++ b/gcc/config/i386/dragonfly.h @@ -34,9 +34,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef ASM_APP_OFF #define ASM_APP_OFF "#NO_APP\n" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) #undef NO_PROFILE_COUNTERS #define NO_PROFILE_COUNTERS 1 diff --git a/gcc/config/i386/freebsd.h b/gcc/config/i386/freebsd.h index 120e24c..9ae8981 100644 --- a/gcc/config/i386/freebsd.h +++ b/gcc/config/i386/freebsd.h @@ -32,9 +32,9 @@ along with GCC; see the file COPYING3. If not see #undef ASM_APP_OFF #define ASM_APP_OFF "#NO_APP\n" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) #undef NO_PROFILE_COUNTERS #define NO_PROFILE_COUNTERS 1 diff --git a/gcc/config/i386/gas.h b/gcc/config/i386/gas.h index 3bac8eb..317bc86 100644 --- a/gcc/config/i386/gas.h +++ b/gcc/config/i386/gas.h @@ -31,15 +31,11 @@ along with GCC; see the file COPYING3. If not see * Next is the question of whether to uses underscores. RMS didn't * like this idea at first, but since it is now obvious that we * need this separate tm file for use with gas, at least to get - * dbx debugging info, I think we should also switch to underscores. + * debugging info, I think we should also switch to underscores. * We can keep i386v for real att style output, and the few * people who want both form will have to compile twice. */ -/* these come from i386/bsd.h, but are specific to sequent */ -#undef DBX_NO_XREFS -#undef DBX_CONTIN_LENGTH - /* Output #ident as a .ident. */ #undef TARGET_ASM_OUTPUT_IDENT diff --git a/gcc/config/i386/gcc-auto-profile b/gcc/config/i386/gcc-auto-profile index 56f64cb..5ab224b 100755 --- a/gcc/config/i386/gcc-auto-profile +++ b/gcc/config/i386/gcc-auto-profile @@ -33,8 +33,15 @@ if grep -q hypervisor /proc/cpuinfo ; then echo >&2 "Warning: branch profiling may not be functional in VMs" fi -case `egrep -q "^cpu family\s*: 6" /proc/cpuinfo && - egrep "^model\s*:" /proc/cpuinfo | head -n1` in +case `grep -E -q "^cpu family\s*: 6" /proc/cpuinfo && + grep -E "^model\s*:" /proc/cpuinfo | head -n1` in +model*:\ 46|\ +model*:\ 30|\ +model*:\ 31|\ +model*:\ 26|\ +model*:\ 47|\ +model*:\ 37|\ +model*:\ 44) E="cpu/event=0x88,umask=0x40/$FLAGS" ;; model*:\ 55|\ model*:\ 77|\ model*:\ 76|\ @@ -43,6 +50,11 @@ model*:\ 95|\ model*:\ 87|\ model*:\ 133|\ model*:\ 122) E="cpu/event=0xC4,umask=0xFE/p$FLAGS" ;; +model*:\ 28|\ +model*:\ 38|\ +model*:\ 39|\ +model*:\ 54|\ +model*:\ 53) E="cpu/event=0x88,umask=0x41/$FLAGS" ;; model*:\ 42|\ model*:\ 45|\ model*:\ 58|\ @@ -63,23 +75,14 @@ model*:\ 165|\ model*:\ 166|\ model*:\ 85|\ model*:\ 85) E="cpu/event=0xC4,umask=0x20/p$FLAGS" ;; -model*:\ 46|\ -model*:\ 30|\ -model*:\ 31|\ -model*:\ 26|\ -model*:\ 47|\ -model*:\ 37|\ -model*:\ 44) E="cpu/event=0x88,umask=0x40/p$FLAGS" ;; -model*:\ 28|\ -model*:\ 38|\ -model*:\ 39|\ -model*:\ 54|\ -model*:\ 53) E="cpu/event=0x88,umask=0x41/p$FLAGS" ;; model*:\ 126|\ model*:\ 140|\ model*:\ 141|\ +model*:\ 143|\ model*:\ 106|\ model*:\ 108) E="cpu/event=0xc4,umask=0x20/p$FLAGS" ;; +model*:\ 134|\ +model*:\ 150) E="cpu/event=0xc4,umask=0xfe/p$FLAGS" ;; *) echo >&2 "Unknown CPU. Run contrib/gen_autofdo_event.py --all --script to update script." exit 1 ;; diff --git a/gcc/config/i386/gnu-user.h b/gcc/config/i386/gnu-user.h index 0102b2a..0f81547 100644 --- a/gcc/config/i386/gnu-user.h +++ b/gcc/config/i386/gnu-user.h @@ -26,9 +26,9 @@ along with GCC; see the file COPYING3. If not see #undef ASM_COMMENT_START #define ASM_COMMENT_START "#" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) /* Output assembler code to FILE to call the profiler. To the best of my knowledge, no GNU userspace libc has required the label diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index acb7e8c..f9c7abd 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -1036,8 +1036,8 @@ BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_vpermilvarv8sf3, "__builtin_ia32_vpe BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_blendpd256, "__builtin_ia32_blendpd256", IX86_BUILTIN_BLENDPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT) BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_blendps256, "__builtin_ia32_blendps256", IX86_BUILTIN_BLENDPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT) -BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_nothing, "__builtin_ia32_blendvpd256", IX86_BUILTIN_BLENDVPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_V4DF) -BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_nothing, "__builtin_ia32_blendvps256", IX86_BUILTIN_BLENDVPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_V8SF) +BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_blendvpd256, "__builtin_ia32_blendvpd256", IX86_BUILTIN_BLENDVPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_V4DF) +BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_blendvps256, "__builtin_ia32_blendvps256", IX86_BUILTIN_BLENDVPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_V8SF) BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_dpps256, "__builtin_ia32_dpps256", IX86_BUILTIN_DPPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT) BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_shufpd256, "__builtin_ia32_shufpd256", IX86_BUILTIN_SHUFPD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT) BDESC (OPTION_MASK_ISA_AVX, 0, CODE_FOR_avx_shufps256, "__builtin_ia32_shufps256", IX86_BUILTIN_SHUFPS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT) diff --git a/gcc/config/i386/i386-d.cc b/gcc/config/i386/i386-d.cc index a62339c..27e2b75 100644 --- a/gcc/config/i386/i386-d.cc +++ b/gcc/config/i386/i386-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/i386/i386-d.h b/gcc/config/i386/i386-d.h new file mode 100644 index 0000000..b980688 --- /dev/null +++ b/gcc/config/i386/i386-d.h @@ -0,0 +1,26 @@ +/* Definitions for the D front end on the x86 architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* In i386-d.cc */ +extern void ix86_d_target_versions (void); +extern void ix86_d_register_target_info (void); +extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS ix86_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info +#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 4b21630..d7b49c9 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -745,6 +745,10 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1) extract = gen_avx_vextractf128v32qi; mode = V16QImode; break; + case E_V16BFmode: + extract = gen_avx_vextractf128v16bf; + mode = V8BFmode; + break; case E_V16HFmode: extract = gen_avx_vextractf128v16hf; mode = V8HFmode; @@ -15030,11 +15034,12 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, machine_mode mode, dperm.op0 = dperm.op1 = gen_reg_rtx (mode); dperm.one_operand_p = true; - if (mode == V8HFmode) + if (mode == V8HFmode || mode == V8BFmode) { - tmp1 = force_reg (HFmode, val); + tmp1 = force_reg (GET_MODE_INNER (mode), val); tmp2 = gen_reg_rtx (mode); - emit_insn (gen_vec_setv8hf_0 (tmp2, CONST0_RTX (mode), tmp1)); + emit_insn (maybe_gen_vec_set_0 (mode, tmp2, + CONST0_RTX (mode), tmp1)); tmp1 = gen_lowpart (mode, tmp2); } else @@ -21822,21 +21827,23 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) return true; case E_V8HFmode: + case E_V8BFmode: /* This can be implemented via interleave and pshufd. */ if (d->testing_p) return true; + rtx (*maybe_gen) (machine_mode, int, rtx, rtx, rtx); if (elt >= nelt2) { - gen = gen_vec_interleave_highv8hf; + maybe_gen = maybe_gen_vec_interleave_high; elt -= nelt2; } else - gen = gen_vec_interleave_lowv8hf; + maybe_gen = maybe_gen_vec_interleave_low; nelt2 /= 2; dest = gen_reg_rtx (vmode); - emit_insn (gen (dest, op0, op0)); + emit_insn (maybe_gen (vmode, 1, dest, op0, op0)); vmode = V4SImode; op0 = gen_lowpart (vmode, dest); diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index d6bb66c..fd212262 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -3268,6 +3268,7 @@ ix86_get_function_versions_dispatcher (void *decl) /* Right now, the dispatching is done via ifunc. */ dispatch_decl = make_dispatcher_decl (default_node->decl); + TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn); dispatcher_node = cgraph_node::get_create (dispatch_decl); gcc_assert (dispatcher_node != NULL); diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index e27c14f..3b94efe 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -277,11 +277,6 @@ extern bool ix86_extract_perm_from_pool_constant (int*, rtx); extern void ix86_target_macros (void); extern void ix86_register_pragmas (void); -/* In i386-d.cc */ -extern void ix86_d_target_versions (void); -extern void ix86_d_register_target_info (void); -extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *); - /* In winnt.cc */ extern void i386_pe_unique_section (tree, int); extern void i386_pe_declare_function_type (FILE *, const char *, int); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index e27c87f..dadf453 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -173,7 +173,7 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] = /* The "default" register map used in 32bit mode. */ -int const dbx_register_map[FIRST_PSEUDO_REGISTER] = +int const debugger_register_map[FIRST_PSEUDO_REGISTER] = { /* general regs */ 0, 2, 1, 3, 6, 7, 4, 5, @@ -204,7 +204,7 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] = /* The "default" register map used in 64bit mode. */ -int const dbx64_register_map[FIRST_PSEUDO_REGISTER] = +int const debugger64_register_map[FIRST_PSEUDO_REGISTER] = { /* general regs */ 0, 1, 2, 3, 4, 5, 6, 7, @@ -283,7 +283,7 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] = 17 for %st(6) (gcc regno = 14) 18 for %st(7) (gcc regno = 15) */ -int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] = +int const svr4_debugger_register_map[FIRST_PSEUDO_REGISTER] = { /* general regs */ 0, 2, 1, 3, 6, 7, 5, 4, @@ -18452,6 +18452,15 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) } break; + case IX86_BUILTIN_PBLENDVB256: + case IX86_BUILTIN_BLENDVPS256: + case IX86_BUILTIN_BLENDVPD256: + /* pcmpeqb/d/q is under avx2, w/o avx2, it's veclower + to scalar operations and not combined back. */ + if (!TARGET_AVX2) + break; + + /* FALLTHRU. */ case IX86_BUILTIN_BLENDVPD: /* blendvpd is under sse4.1 but pcmpgtq is under sse4.2, w/o sse4.2, it's veclowered to scalar operations and @@ -18460,10 +18469,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) break; /* FALLTHRU. */ case IX86_BUILTIN_PBLENDVB128: - case IX86_BUILTIN_PBLENDVB256: case IX86_BUILTIN_BLENDVPS: - case IX86_BUILTIN_BLENDVPS256: - case IX86_BUILTIN_BLENDVPD256: gcc_assert (n_args == 3); arg0 = gimple_call_arg (stmt, 0); arg1 = gimple_call_arg (stmt, 1); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 0de5c77..900a3bc 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -608,11 +608,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* Target Pragmas. */ #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas () -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS ix86_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info -#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention - #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " #endif @@ -2035,14 +2030,14 @@ do { \ { "zmm28", XMM28_REG }, { "zmm29", XMM29_REG }, { "zmm30", XMM30_REG }, { "zmm31", XMM31_REG } \ } -/* How to renumber registers for dbx and gdb. */ +/* How to renumber registers for gdb. */ -#define DBX_REGISTER_NUMBER(N) \ - (TARGET_64BIT ? dbx64_register_map[(N)] : dbx_register_map[(N)]) +#define DEBUGGER_REGNO(N) \ + (TARGET_64BIT ? debugger64_register_map[(N)] : debugger_register_map[(N)]) -extern int const dbx_register_map[FIRST_PSEUDO_REGISTER]; -extern int const dbx64_register_map[FIRST_PSEUDO_REGISTER]; -extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER]; +extern int const debugger_register_map[FIRST_PSEUDO_REGISTER]; +extern int const debugger64_register_map[FIRST_PSEUDO_REGISTER]; +extern int const svr4_debugger_register_map[FIRST_PSEUDO_REGISTER]; /* Before the prologue, RA is at 0(%esp). */ #define INCOMING_RETURN_ADDR_RTX \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 58fcc38..1aef1af 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3043,8 +3043,8 @@ [(set (match_operand:SWI48 0 "general_reg_operand") (match_operand:SWI48 1 "general_reg_operand"))] "optimize_size > 1 - && (REGNO (operands[0]) == AX_REG - || REGNO (operands[1]) == AX_REG) + && ((REGNO (operands[0]) == AX_REG) + != (REGNO (operands[1]) == AX_REG)) && optimize_insn_for_size_p () && peep2_reg_dead_p (1, operands[1])" [(parallel [(set (match_dup 0) (match_dup 1)) @@ -24732,6 +24732,58 @@ DONE; }) +;; Defined because the generic expand_builtin_issignaling for XFmode +;; only tests for sNaNs, but i387 treats also pseudo numbers as always +;; signaling. +(define_expand "issignalingxf2" + [(match_operand:SI 0 "register_operand") + (match_operand:XF 1 "general_operand")] + "" +{ + rtx temp = operands[1]; + if (!MEM_P (temp)) + { + rtx mem = assign_stack_temp (XFmode, GET_MODE_SIZE (XFmode)); + emit_move_insn (mem, temp); + temp = mem; + } + rtx ex = adjust_address (temp, HImode, 8); + rtx hi = adjust_address (temp, SImode, 4); + rtx lo = adjust_address (temp, SImode, 0); + rtx val = GEN_INT (HOST_WIDE_INT_M1U << 30); + rtx mask = GEN_INT (0x7fff); + rtx bit = GEN_INT (HOST_WIDE_INT_1U << 30); + /* Expand to: + ((ex & mask) && (int) hi >= 0) + || ((ex & mask) == mask && ((hi ^ bit) | ((lo | -lo) >> 31)) > val). */ + rtx nlo = expand_unop (SImode, neg_optab, lo, NULL_RTX, 0); + lo = expand_binop (SImode, ior_optab, lo, nlo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + lo = expand_shift (RSHIFT_EXPR, SImode, lo, 31, NULL_RTX, 1); + temp = expand_binop (SImode, xor_optab, hi, bit, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (SImode, ior_optab, temp, lo, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = emit_store_flag_force (gen_reg_rtx (SImode), GTU, temp, val, + SImode, 1, 1); + ex = expand_binop (HImode, and_optab, ex, mask, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + rtx temp2 = emit_store_flag_force (gen_reg_rtx (SImode), NE, + ex, const0_rtx, SImode, 1, 1); + ex = emit_store_flag_force (gen_reg_rtx (SImode), EQ, + ex, mask, HImode, 1, 1); + temp = expand_binop (SImode, and_optab, temp, ex, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + rtx temp3 = emit_store_flag_force (gen_reg_rtx (SImode), GE, + hi, const0_rtx, SImode, 0, 1); + temp2 = expand_binop (SImode, and_optab, temp2, temp3, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + temp = expand_binop (SImode, ior_optab, temp, temp2, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + emit_move_insn (operands[0], temp); + DONE; +}) + (include "mmx.md") (include "sse.md") (include "sync.md") diff --git a/gcc/config/i386/i386elf.h b/gcc/config/i386/i386elf.h index 50f7067..696a81c 100644 --- a/gcc/config/i386/i386elf.h +++ b/gcc/config/i386/i386elf.h @@ -36,9 +36,9 @@ along with GCC; see the file COPYING3. If not see %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ crtbegin.o%s" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) #define LOCAL_LABEL_PREFIX "." diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h index ff94cc5..ceebbd0 100644 --- a/gcc/config/i386/iamcu.h +++ b/gcc/config/i386/iamcu.h @@ -33,9 +33,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef ASM_COMMENT_START #define ASM_COMMENT_START "#" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) #undef ASM_SPEC #define ASM_SPEC "--32 -march=iamcu" diff --git a/gcc/config/i386/lynx.h b/gcc/config/i386/lynx.h index baa62c1..1e6d3cc 100644 --- a/gcc/config/i386/lynx.h +++ b/gcc/config/i386/lynx.h @@ -37,9 +37,9 @@ along with GCC; see the file COPYING3. If not see /* LynxOS's GDB counts the floating point registers from 16. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] \ +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] \ : (n) == 0 ? 0 \ : (n) == 1 ? 2 \ : (n) == 2 ? 1 \ diff --git a/gcc/config/i386/netbsd-elf.h b/gcc/config/i386/netbsd-elf.h index b1d7d48..10fa945 100644 --- a/gcc/config/i386/netbsd-elf.h +++ b/gcc/config/i386/netbsd-elf.h @@ -66,8 +66,8 @@ along with GCC; see the file COPYING3. If not see #undef ASM_COMMENT_START #define ASM_COMMENT_START "#" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n] +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) svr4_debugger_register_map[n] /* Output assembler code to FILE to call the profiler. */ diff --git a/gcc/config/i386/nto.h b/gcc/config/i386/nto.h index 5df3009..85418b2 100644 --- a/gcc/config/i386/nto.h +++ b/gcc/config/i386/nto.h @@ -100,4 +100,4 @@ crti.o%s \ #define TARGET_POSIX_IO -#undef DBX_REGISTER_NUMBER +#undef DEBUGGER_REGNO diff --git a/gcc/config/i386/openbsdelf.h b/gcc/config/i386/openbsdelf.h index 2176e79..fc6597c 100644 --- a/gcc/config/i386/openbsdelf.h +++ b/gcc/config/i386/openbsdelf.h @@ -25,9 +25,9 @@ along with GCC; see the file COPYING3. If not see } \ while (0) -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) /* This must agree with <machine/_types.h>. */ #undef SIZE_TYPE diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 9351548..72acf0b 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -297,9 +297,9 @@ (define_mode_iterator V_256 [V32QI V16HI V8SI V4DI V8SF V4DF]) -;; All 256bit vector modes including HF vector mode +;; All 256bit vector modes including HF/BF vector modes (define_mode_iterator V_256H - [V32QI V16HI V8SI V4DI V8SF V4DF V16HF]) + [V32QI V16HI V8SI V4DI V8SF V4DF V16HF V16BF]) ;; All 128bit and 256bit vector modes (define_mode_iterator V_128_256 @@ -747,7 +747,8 @@ (V8HI "avx512vl") (V16HI "avx512vl") (V32HI "avx512bw")]) (define_mode_attr shuffletype - [(V32HF "f") (V16HF "f") (V8HF "f") + [(V32HF "i") (V16HF "i") (V8HF "i") + (V32BF "i") (V16BF "i") (V8BF "i") (V16SF "f") (V16SI "i") (V8DF "f") (V8DI "i") (V8SF "f") (V8SI "i") (V4DF "f") (V4DI "i") (V4SF "f") (V4SI "i") (V2DF "f") (V2DI "i") @@ -983,6 +984,7 @@ (V16SI "QI") (V8SI "QI") (V4SI "QI") (V8DI "QI") (V4DI "QI") (V2DI "QI") (V32HF "HI") (V16HF "QI") (V8HF "QI") + (V32BF "HI") (V16BF "QI") (V8BF "QI") (V16SF "QI") (V8SF "QI") (V4SF "QI") (V8DF "QI") (V4DF "QI") (V2DF "QI")]) @@ -1136,10 +1138,10 @@ [(V64QI "b") (V32HI "w") (V16SI "k") (V8DI "q") (V32QI "b") (V16HI "w") (V8SI "k") (V4DI "q") (V16QI "b") (V8HI "w") (V4SI "k") (V2DI "q") - (V32HF "w") (V16SF "k") (V8DF "q") - (V16HF "w") (V8SF "k") (V4DF "q") - (V8HF "w") (V4SF "k") (V2DF "q") - (HF "w") (SF "k") (DF "q")]) + (V32HF "w") (V32BF "w") (V16SF "k") (V8DF "q") + (V16HF "w") (V16BF "w") (V8SF "k") (V4DF "q") + (V8HF "w") (V8BF "w") (V4SF "k") (V2DF "q") + (HF "w") (BF "w") (SF "k") (DF "q")]) ;; Mapping of vector modes to VPTERNLOG suffix (define_mode_attr ternlogsuffix @@ -1251,7 +1253,7 @@ ;; For 256-bit modes for TARGET_AVX512VL && TARGET_AVX512DQ ;; i32x4, f32x4, i64x2 or f64x2 suffixes. (define_mode_attr i128vldq - [(V8SF "f32x4") (V4DF "f64x2") + [(V16HF "i32x4") (V16BF "i32x4") (V8SF "f32x4") (V4DF "f64x2") (V32QI "i32x4") (V16HI "i32x4") (V8SI "i32x4") (V4DI "i64x2")]) ;; Mix-n-match @@ -10711,7 +10713,7 @@ ] (symbol_ref "true")))]) -(define_insn "vec_set<mode>_0" +(define_insn "@vec_set<mode>_0" [(set (match_operand:V8_128 0 "register_operand" "=v,v,v,x,x,Yr,*x,x,x,x,v,v") (vec_merge:V8_128 @@ -17894,7 +17896,7 @@ (set_attr "prefix" "maybe_evex") (set_attr "mode" "OI")]) -(define_insn "vec_interleave_high<mode><mask_name>" +(define_insn "@vec_interleave_high<mode><mask_name>" [(set (match_operand:V8_128 0 "register_operand" "=x,Yw") (vec_select:V8_128 (vec_concat:<ssedoublevecmode> @@ -17962,7 +17964,7 @@ (set_attr "prefix" "maybe_evex") (set_attr "mode" "OI")]) -(define_insn "vec_interleave_low<mode><mask_name>" +(define_insn "@vec_interleave_low<mode><mask_name>" [(set (match_operand:V8_128 0 "register_operand" "=x,Yw") (vec_select:V8_128 (vec_concat:<ssedoublevecmode> @@ -23897,7 +23899,7 @@ (match_operand:VF_128 2 "register_operand" "v") (const_int 1)))] "TARGET_AVX512ER" - "vrcp28<ssescalarmodesuffix>\t{<round_saeonly_mask_op3>%1, %2, %0<mask_operand3>|<mask_opernad3>%0, %2, %<iptr>1<round_saeonly_mask_op3>}" + "vrcp28<ssescalarmodesuffix>\t{<round_saeonly_mask_op3>%1, %2, %0<mask_operand3>|<mask_operand3>%0, %2, %<iptr>1<round_saeonly_mask_op3>}" [(set_attr "length_immediate" "1") (set_attr "prefix" "evex") (set_attr "type" "sse") diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md index 0b75882..e169282 100644 --- a/gcc/config/i386/subst.md +++ b/gcc/config/i386/subst.md @@ -25,6 +25,7 @@ V16SI V8SI V4SI V8DI V4DI V2DI V32HF V16HF V8HF + V32BF V16BF V8BF V16SF V8SF V4SF V8DF V4DF V2DF]) diff --git a/gcc/config/i386/sysv4.h b/gcc/config/i386/sysv4.h index b7db957..3c4c11c 100644 --- a/gcc/config/i386/sysv4.h +++ b/gcc/config/i386/sysv4.h @@ -26,8 +26,8 @@ along with GCC; see the file COPYING3. If not see #undef X86_FILE_START_VERSION_DIRECTIVE #define X86_FILE_START_VERSION_DIRECTIVE true -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n] +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) svr4_debugger_register_map[n] /* A C statement (sans semicolon) to output to the stdio stream FILE the assembler definition of uninitialized global DECL named diff --git a/gcc/config/i386/vxworks.h b/gcc/config/i386/vxworks.h index 3b8eb6f..f23bdf4 100644 --- a/gcc/config/i386/vxworks.h +++ b/gcc/config/i386/vxworks.h @@ -54,12 +54,12 @@ along with GCC; see the file COPYING3. If not see #endif -/* Provide our target specific DBX_REGISTER_NUMBER. VxWorks relies on +/* Provide our target specific DEBUGGER_REGNO. VxWorks relies on the SVR4 numbering. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) /* CPU macro definitions, ordered to account for VxWorks 7 not supporting CPUs older than PENTIUM4 since SR0650. */ diff --git a/gcc/config/i386/winnt-d.cc b/gcc/config/i386/winnt-d.cc index 3d990a1..00c28c3 100644 --- a/gcc/config/i386/winnt-d.cc +++ b/gcc/config/i386/winnt-d.cc @@ -21,9 +21,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "target.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" -#include "tm_p.h" /* Implement TARGET_D_OS_VERSIONS for Windows targets. */ diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h index 0652699..55aeb95 100644 --- a/gcc/config/i386/x86-64.h +++ b/gcc/config/i386/x86-64.h @@ -26,9 +26,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef ASM_COMMENT_START #define ASM_COMMENT_START "#" -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) \ - (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(n) \ + (TARGET_64BIT ? debugger64_register_map[n] : svr4_debugger_register_map[n]) /* Output assembler code to FILE to call the profiler. */ #define NO_PROFILE_COUNTERS 1 diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 77e0cf7..23b63c8 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -83,7 +83,7 @@ extern int ia64_epilogue_uses (int); extern int ia64_eh_uses (int); extern void emit_safe_across_calls (void); extern void ia64_init_builtins (void); -extern int ia64_dbx_register_number (int); +extern int ia64_debugger_regno (int); extern rtx ia64_return_addr_rtx (HOST_WIDE_INT, rtx); extern void ia64_split_return_addr_rtx (rtx); diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc index 25e4a47..50ae7aa 100644 --- a/gcc/config/ia64/ia64.cc +++ b/gcc/config/ia64/ia64.cc @@ -4421,7 +4421,7 @@ ia64_output_function_prologue (FILE *file) if (mask && TARGET_GNU_AS) fprintf (file, "\t.prologue %d, %d\n", mask, - ia64_dbx_register_number (grsave)); + ia64_debugger_regno (grsave)); else fputs ("\t.prologue\n", file); @@ -4473,7 +4473,7 @@ ia64_output_function_epilogue (FILE *) } int -ia64_dbx_register_number (int regno) +ia64_debugger_regno (int regno) { /* In ia64_expand_prologue we quite literally renamed the frame pointer from its home at loc79 to something inside the register frame. We @@ -10104,7 +10104,7 @@ process_cfa_adjust_cfa (FILE *out_file, rtx pat, rtx insn, if (unwind) fprintf (out_file, "\t.vframe r%d\n", - ia64_dbx_register_number (REGNO (dest))); + ia64_debugger_regno (REGNO (dest))); } else gcc_unreachable (); @@ -10125,7 +10125,7 @@ process_cfa_register (FILE *out_file, rtx pat, bool unwind) /* Saving return address pointer. */ if (unwind) fprintf (out_file, "\t.save rp, r%d\n", - ia64_dbx_register_number (dest_regno)); + ia64_debugger_regno (dest_regno)); return; } @@ -10137,21 +10137,21 @@ process_cfa_register (FILE *out_file, rtx pat, bool unwind) gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); if (unwind) fprintf (out_file, "\t.save pr, r%d\n", - ia64_dbx_register_number (dest_regno)); + ia64_debugger_regno (dest_regno)); break; case AR_UNAT_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); if (unwind) fprintf (out_file, "\t.save ar.unat, r%d\n", - ia64_dbx_register_number (dest_regno)); + ia64_debugger_regno (dest_regno)); break; case AR_LC_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); if (unwind) fprintf (out_file, "\t.save ar.lc, r%d\n", - ia64_dbx_register_number (dest_regno)); + ia64_debugger_regno (dest_regno)); break; default: @@ -10326,7 +10326,7 @@ ia64_asm_unwind_emit (FILE *out_file, rtx_insn *insn) { if (unwind) fprintf (out_file, "\t.save ar.pfs, r%d\n", - ia64_dbx_register_number (dest_regno)); + ia64_debugger_regno (dest_regno)); } else { diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index bd0ef35e..b7415c5 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1422,22 +1422,6 @@ do { \ /* Macros Affecting all Debug Formats. */ /* This is handled in sysv4.h. */ - - -/* Specific Options for DBX Output. */ - -/* This is handled by dbxelf.h. */ - - -/* Open ended Hooks for DBX Output. */ - -/* Likewise. */ - - -/* File names in DBX format. */ - -/* Likewise. */ - /* Macros for Dwarf Output. */ diff --git a/gcc/config/ia64/sysv4.h b/gcc/config/ia64/sysv4.h index 045752a..6a4e017 100644 --- a/gcc/config/ia64/sysv4.h +++ b/gcc/config/ia64/sysv4.h @@ -30,9 +30,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -/* Stabs does not work properly for 64-bit targets. */ -#undef DBX_DEBUGGING_INFO - /* Various pseudo-ops for which the Intel assembler uses non-standard definitions. */ @@ -103,8 +100,8 @@ do { \ #undef FINI_SECTION_ASM_OP #define FINI_SECTION_ASM_OP "\t.section\t.fini,\"ax\",\"progbits\"" -#define DBX_REGISTER_NUMBER(REGNO) \ - ia64_dbx_register_number(REGNO) +#define DEBUGGER_REGNO(REGNO) \ + ia64_debugger_regno(REGNO) #undef SIZE_TYPE #define SIZE_TYPE "long unsigned int" diff --git a/gcc/config/lm32/lm32.h b/gcc/config/lm32/lm32.h index 23f66c9..3090185 100644 --- a/gcc/config/lm32/lm32.h +++ b/gcc/config/lm32/lm32.h @@ -491,7 +491,7 @@ do { \ /* Debugging. */ /*-------------*/ -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#define DEBUGGER_REGNO(REGNO) (REGNO) #define DEFAULT_GDB_EXTENSIONS 1 diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h index cadaad7..77b2217 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -28,7 +28,12 @@ along with GCC; see the file COPYING3. If not see The symbol's value will be loaded directly from the GOT. SYMBOL_PCREL - The symbol's value will be loaded directly from data section. + The symbol's value will be loaded directly from data section within + +/- 2GiB range. + + SYMBOL_PCREL64 + The symbol's value will be loaded directly from data section within + +/- 8EiB range. SYMBOL_TLS A thread-local symbol. @@ -42,6 +47,7 @@ along with GCC; see the file COPYING3. If not see enum loongarch_symbol_type { SYMBOL_GOT_DISP, SYMBOL_PCREL, + SYMBOL_PCREL64, SYMBOL_TLS, SYMBOL_TLS_IE, SYMBOL_TLS_LE, diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 16fd4ac..77e3a10 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -1500,8 +1500,8 @@ loongarch_build_integer (struct loongarch_integer_op *codes, bool lu32i[2] = {(value & LU32I_B) == 0, (value & LU32I_B) == LU32I_B}; bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B}; - int sign31 = (value & (1UL << 31)) >> 31; - int sign51 = (value & (1UL << 51)) >> 51; + int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31; + int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51; /* Determine whether the upper 32 bits are sign-extended from the lower 32 bits. If it is, the instructions to load the high order can be ommitted. */ @@ -1522,7 +1522,7 @@ loongarch_build_integer (struct loongarch_integer_op *codes, /* Determine whether the 52-61 bits are sign-extended from the low order, and if not, load the 52-61 bits. */ - if (!lu52i[(value & (1ULL << 51)) >> 51]) + if (!lu52i[(value & (HOST_WIDE_INT_1U << 51)) >> 51]) { codes[cost].method = METHOD_LU52I; codes[cost].value = value & LU52I_B; @@ -1633,17 +1633,40 @@ loongarch_rtx_constant_in_small_data_p (machine_mode mode) static enum loongarch_symbol_type loongarch_classify_symbol (const_rtx x) { - if (LABEL_REF_P (x)) - return SYMBOL_PCREL; + enum loongarch_symbol_type pcrel = + TARGET_CMODEL_EXTREME ? SYMBOL_PCREL64 : SYMBOL_PCREL; + + if (!SYMBOL_REF_P (x)) + return pcrel; if (SYMBOL_REF_TLS_MODEL (x)) return SYMBOL_TLS; - if (SYMBOL_REF_P (x) - && !loongarch_symbol_binds_local_p (x)) + if (!loongarch_symbol_binds_local_p (x)) return SYMBOL_GOT_DISP; - return SYMBOL_PCREL; + tree t = SYMBOL_REF_DECL (x); + if (!t) + return pcrel; + + t = lookup_attribute ("model", DECL_ATTRIBUTES (t)); + if (!t) + return pcrel; + + t = TREE_VALUE (TREE_VALUE (t)); + + /* loongarch_handle_model_attribute should reject other values. */ + gcc_assert (TREE_CODE (t) == STRING_CST); + + const char *model = TREE_STRING_POINTER (t); + if (strcmp (model, "normal") == 0) + return SYMBOL_PCREL; + if (strcmp (model, "extreme") == 0) + return SYMBOL_PCREL64; + + /* loongarch_handle_model_attribute should reject unknown model + name. */ + gcc_unreachable (); } /* Classify the base of symbolic expression X, given that X appears in @@ -1696,6 +1719,7 @@ loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type) case SYMBOL_TLSGD: case SYMBOL_TLSLDM: case SYMBOL_PCREL: + case SYMBOL_PCREL64: /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */ return sext_hwi (INTVAL (offset), 32) == INTVAL (offset); @@ -1730,6 +1754,9 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode) case SYMBOL_TLSLDM: return 3; + case SYMBOL_PCREL64: + return 5; + case SYMBOL_TLS: /* We don't treat a bare TLS symbol as a constant. */ return 0; @@ -1834,7 +1861,7 @@ loongarch_valid_offset_p (rtx x, machine_mode mode) return true; } -/* Should a symbol of type SYMBOL_TYPE should be split in two? */ +/* Should a symbol of type SYMBOL_TYPE should be split in two or more? */ bool loongarch_split_symbol_type (enum loongarch_symbol_type symbol_type) @@ -1842,6 +1869,7 @@ loongarch_split_symbol_type (enum loongarch_symbol_type symbol_type) switch (symbol_type) { case SYMBOL_PCREL: + case SYMBOL_PCREL64: case SYMBOL_GOT_DISP: case SYMBOL_TLS_IE: case SYMBOL_TLS_LE: @@ -2719,6 +2747,20 @@ loongarch_force_address (rtx x, machine_mode mode) return x; } +static bool +loongarch_symbol_extreme_p (enum loongarch_symbol_type type) +{ + switch (type) + { + case SYMBOL_PCREL: + return false; + case SYMBOL_PCREL64: + return true; + default: + return TARGET_CMODEL_EXTREME; + } +} + /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise it appears in a MEM of that mode. Return true if ADDR is a legitimate constant in that context and can be split into high and low parts. @@ -2758,7 +2800,7 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out) high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); high = loongarch_force_temporary (temp, high); - if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ()) + if (loongarch_symbol_extreme_p (symbol_type) && can_create_pseudo_p ()) { gcc_assert (TARGET_EXPLICIT_RELOCS); @@ -2772,14 +2814,16 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out) if (low_out) switch (symbol_type) { - case SYMBOL_PCREL: - { - if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ()) + case SYMBOL_PCREL64: + if (can_create_pseudo_p ()) + { *low_out = gen_rtx_PLUS (Pmode, high, temp1); - else - *low_out = gen_rtx_LO_SUM (Pmode, high, addr); - break; - } + break; + } + /* fall through */ + case SYMBOL_PCREL: + *low_out = gen_rtx_LO_SUM (Pmode, high, addr); + break; case SYMBOL_GOT_DISP: /* SYMBOL_GOT_DISP symbols are loaded from the GOT. */ @@ -4746,22 +4790,23 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part, bool hi_reloc) { const char *reloc; + enum loongarch_symbol_type symbol_type = + loongarch_classify_symbolic_expression (op); - if (TARGET_CMODEL_EXTREME) + if (loongarch_symbol_extreme_p (symbol_type)) gcc_assert (TARGET_EXPLICIT_RELOCS); - switch (loongarch_classify_symbolic_expression (op)) + switch (symbol_type) { - case SYMBOL_PCREL: + case SYMBOL_PCREL64: if (hi64_part) { - if (TARGET_CMODEL_EXTREME) - reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20"; - else - gcc_unreachable (); + reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20"; + break; } - else - reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12"; + /* fall through */ + case SYMBOL_PCREL: + reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12"; break; case SYMBOL_GOT_DISP: @@ -6317,6 +6362,104 @@ loongarch_starting_frame_offset (void) return crtl->outgoing_args_size; } +static tree +loongarch_handle_model_attribute (tree *node, tree name, tree arg, int, + bool *no_add_attrs) +{ + tree decl = *node; + if (TREE_CODE (decl) == VAR_DECL) + { + if (DECL_THREAD_LOCAL_P (decl)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute cannot be specified for thread-local " + "variables", name); + *no_add_attrs = true; + return NULL_TREE; + } + if (DECL_CONTEXT (decl) + && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL + && !TREE_STATIC (decl)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute cannot be specified for local " + "variables", name); + *no_add_attrs = true; + return NULL_TREE; + } + if (DECL_REGISTER (decl)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute cannot be specified for register " + "variables", name); + *no_add_attrs = true; + return NULL_TREE; + } + if (!TARGET_EXPLICIT_RELOCS) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute requires %s", name, "-mexplicit-relocs"); + *no_add_attrs = true; + return NULL_TREE; + } + + arg = TREE_VALUE (arg); + if (TREE_CODE (arg) != STRING_CST) + { + error_at (DECL_SOURCE_LOCATION (decl), + "invalid argument of %qE attribute", name); + *no_add_attrs = true; + return NULL_TREE; + } + + const char *model = TREE_STRING_POINTER (arg); + if (strcmp (model, "normal") != 0 + && strcmp (model, "extreme") != 0) + { + error_at (DECL_SOURCE_LOCATION (decl), + "invalid argument of %qE attribute", name); + *no_add_attrs = true; + return NULL_TREE; + } + + if (lookup_attribute ("model", DECL_ATTRIBUTES (decl))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "multiple %qE attribute", name); + *no_add_attrs = true; + return NULL_TREE; + } + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + return NULL_TREE; +} + +static const struct attribute_spec loongarch_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, + affects_type_identity, handler, exclude } */ + { "model", 1, 1, true, false, false, false, + loongarch_handle_model_attribute, NULL }, + /* The last attribute spec is set to be NULL. */ + {} +}; + +bool +loongarch_use_anchors_for_symbol_p (const_rtx symbol) +{ + tree decl = SYMBOL_REF_DECL (symbol); + + /* The section anchor optimization may break custom address model. */ + if (decl && lookup_attribute ("model", DECL_ATTRIBUTES (decl))) + return false; + + return default_use_anchors_for_symbol_p (symbol); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -6505,6 +6648,12 @@ loongarch_starting_frame_offset (void) #undef TARGET_HAVE_SPECULATION_SAFE_VALUE #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE loongarch_attribute_table + +#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P +#define TARGET_USE_ANCHORS_FOR_SYMBOL_P loongarch_use_anchors_for_symbol_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-loongarch.h" diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h index 8b12889..f4a9c32 100644 --- a/gcc/config/loongarch/loongarch.h +++ b/gcc/config/loongarch/loongarch.h @@ -561,7 +561,8 @@ enum reg_class 64, 65, 66, 67, 68, 69, 70, 71, 72, 73} #define IMM_BITS 12 -#define IMM_REACH (1LL << IMM_BITS) +#define IMM_REACH (HOST_WIDE_INT_1 << IMM_BITS) +#define HWIT_1U HOST_WIDE_INT_1U /* True if VALUE is an unsigned 6-bit number. */ @@ -589,18 +590,20 @@ enum reg_class /* True if VALUE can be loaded into a register using LU12I. */ #define LU12I_OPERAND(VALUE) \ - (((VALUE) | ((1UL << 31) - IMM_REACH)) == ((1UL << 31) - IMM_REACH) \ - || ((VALUE) | ((1UL << 31) - IMM_REACH)) + IMM_REACH == 0) + (((VALUE) | ((HWIT_1U << 31) - IMM_REACH)) == ((HWIT_1U << 31) - IMM_REACH) \ + || ((VALUE) | ((HWIT_1U << 31) - IMM_REACH)) + IMM_REACH == 0) /* True if VALUE can be loaded into a register using LU32I. */ #define LU32I_OPERAND(VALUE) \ - (((VALUE) | (((1ULL << 19) - 1) << 32)) == (((1ULL << 19) - 1) << 32) \ - || ((VALUE) | (((1ULL << 19) - 1) << 32)) + (1ULL << 32) == 0) + (((VALUE) | (((HWIT_1U << 19) - 1) << 32)) == (((HWIT_1U << 19) - 1) << 32) \ + || ((VALUE) | (((HWIT_1U << 19) - 1) << 32)) + (HWIT_1U << 32) == 0) /* True if VALUE can be loaded into a register using LU52I. */ -#define LU52I_OPERAND(VALUE) (((VALUE) | (0xfffULL << 52)) == (0xfffULL << 52)) +#define HWIT_UC_0xFFF HOST_WIDE_INT_UC(0xfff) +#define LU52I_OPERAND(VALUE) \ + (((VALUE) | (HWIT_UC_0xFFF << 52)) == (HWIT_UC_0xFFF << 52)) /* Return a value X with the low 12 bits clear, and such that VALUE - X is a signed 12-bit value. */ diff --git a/gcc/config/m32c/m32c.cc b/gcc/config/m32c/m32c.cc index 5a19faa..26601ab 100644 --- a/gcc/config/m32c/m32c.cc +++ b/gcc/config/m32c/m32c.cc @@ -1013,7 +1013,7 @@ m32c_eh_return_stackadj_rtx (void) /* Registers That Address the Stack Frame */ -/* Implements DWARF_FRAME_REGNUM and DBX_REGISTER_NUMBER. Note that +/* Implements DWARF_FRAME_REGNUM and DEBUGGER_REGNO. Note that the original spec called for dwarf numbers to vary with register width as well, for example, r0l, r0, and r2r0 would each have different dwarf numbers. GCC doesn't support this, and we don't do diff --git a/gcc/config/m32c/m32c.h b/gcc/config/m32c/m32c.h index af99103..a9b61ac 100644 --- a/gcc/config/m32c/m32c.h +++ b/gcc/config/m32c/m32c.h @@ -452,7 +452,7 @@ enum reg_class #define DWARF_FRAME_REGISTERS 20 #define DWARF_FRAME_REGNUM(N) m32c_dwarf_frame_regnum (N) -#define DBX_REGISTER_NUMBER(N) m32c_dwarf_frame_regnum (N) +#define DEBUGGER_REGNO(N) m32c_dwarf_frame_regnum (N) #undef ASM_PREFERRED_EH_DATA_FORMAT /* This is the same as the default in practice, except that by making diff --git a/gcc/config/m32c/rtems.h b/gcc/config/m32c/rtems.h deleted file mode 100644 index 553f77c..0000000 --- a/gcc/config/m32c/rtems.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Definitions for rtems targeting a M32C using ELF. - Copyright (C) 2008-2022 Free Software Foundation, Inc. - Contributed by Joel Sherrill (joel@OARcorp.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GCC is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -/* Target OS builtins. */ -#undef TARGET_OS_CPP_BUILTINS -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_define ("__rtems__"); \ - builtin_define ("__USE_INIT_FINI__"); \ - builtin_assert ("system=rtems"); \ - } \ - while (0) - -/* Use the default */ -#undef LINK_GCC_C_SEQUENCE_SPEC diff --git a/gcc/config/m68k/linux.h b/gcc/config/m68k/linux.h index 05661bf..ba7a3ba 100644 --- a/gcc/config/m68k/linux.h +++ b/gcc/config/m68k/linux.h @@ -146,10 +146,6 @@ along with GCC; see the file COPYING3. If not see fprintf (FILE, "\tjbsr _mcount\n"); \ } -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - /* 1 if N is a possible register number for a function value. For m68k/SVR4 allow d0, a0, or fp0 as return registers, for integral, pointer, or floating types, respectively. Reject fp0 if not using @@ -228,8 +224,8 @@ along with GCC; see the file COPYING3. If not see #define TARGET_ASM_FILE_END file_end_indicate_exec_stack -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(REGNO) (REGNO) #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index cd353db..05fa7fe8 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -707,7 +707,7 @@ __transfer_from_trampoline () \ /* On the Sun-3, the floating point registers have numbers 18 to 25, not 16 to 23 as they do in the compiler. */ -#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2) +#define DEBUGGER_REGNO(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2) /* Before the prologue, RA is at 0(%sp). */ #define INCOMING_RETURN_ADDR_RTX \ @@ -720,7 +720,7 @@ __transfer_from_trampoline () \ UNITS_PER_WORD)) \ : gen_rtx_MEM (Pmode, plus_constant (Pmode, FRAME, UNITS_PER_WORD))) -/* We must not use the DBX register numbers for the DWARF 2 CFA column +/* We must not use the debugger register numbers for the DWARF 2 CFA column numbers because that maps to numbers beyond FIRST_PSEUDO_REGISTER. Instead use the identity mapping. */ #define DWARF_FRAME_REGNUM(REG) \ diff --git a/gcc/config/m68k/m68kelf.h b/gcc/config/m68k/m68kelf.h index 8133e64..e5518b0 100644 --- a/gcc/config/m68k/m68kelf.h +++ b/gcc/config/m68k/m68kelf.h @@ -100,8 +100,8 @@ do { \ SVR4 debugger in the m68k/SVR4 reference port, where d0-d7 are 0-7, a0-a8 are 8-15, and fp0-fp7 are 16-23. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(REGNO) (REGNO) #if 0 /* SVR4 m68k assembler is bitching on the `comm i,1,1' which askes for diff --git a/gcc/config/m68k/netbsd-elf.h b/gcc/config/m68k/netbsd-elf.h index d262b60..ac7ec92 100644 --- a/gcc/config/m68k/netbsd-elf.h +++ b/gcc/config/m68k/netbsd-elf.h @@ -215,13 +215,13 @@ while (0) #define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1" -/* Now to renumber registers for dbx and gdb. +/* Now to renumber registers for gdb. We use the Sun-3 convention, which is: floating point registers have numbers 18 to 25, not 16 to 23 as they do in the compiler. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(REGNO) ((REGNO) < 16 ? (REGNO) : (REGNO) + 2) /* 1 if N is a possible register number for a function value. For diff --git a/gcc/config/m68k/openbsd.h b/gcc/config/m68k/openbsd.h index 63c57fd..ab99817 100644 --- a/gcc/config/m68k/openbsd.h +++ b/gcc/config/m68k/openbsd.h @@ -60,18 +60,6 @@ along with GCC; see the file COPYING3. If not see /* Every structure or union's size must be a multiple of 2 bytes. */ #define STRUCTURE_SIZE_BOUNDARY 16 -/* Specific options for DBX Output. */ - -/* This is BSD, so it wants DBX format. */ -#define DBX_DEBUGGING_INFO 1 - -/* Do not break .stabs pseudos into continuations. */ -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ -#define DBX_CONTIN_CHAR '?' - /* Stack & calling: aggregate returns. */ /* ??? This is traditional, but quite possibly wrong. It appears to diff --git a/gcc/config/microblaze/microblaze.cc b/gcc/config/microblaze/microblaze.cc index f32effe..8fcca18 100644 --- a/gcc/config/microblaze/microblaze.cc +++ b/gcc/config/microblaze/microblaze.cc @@ -193,7 +193,7 @@ struct microblaze_frame_info zero_frame_info; char microblaze_print_operand_punct[256]; /* Map GCC register number to debugger register number. */ -int microblaze_dbx_regno[FIRST_PSEUDO_REGISTER]; +int microblaze_debugger_regno[FIRST_PSEUDO_REGISTER]; /* Map hard register number to register class. */ enum reg_class microblaze_regno_to_class[] = @@ -1881,11 +1881,11 @@ microblaze_option_override (void) Ignore the special purpose register numbers. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - microblaze_dbx_regno[i] = -1; + microblaze_debugger_regno[i] = -1; - start = GP_DBX_FIRST - GP_REG_FIRST; + start = GP_DEBUGGER_FIRST - GP_REG_FIRST; for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++) - microblaze_dbx_regno[i] = i + start; + microblaze_debugger_regno[i] = i + start; /* Set up array giving whether a given register can hold a given mode. */ diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h index d28bc76..f70c661 100644 --- a/gcc/config/microblaze/microblaze.h +++ b/gcc/config/microblaze/microblaze.h @@ -39,7 +39,7 @@ extern char microblaze_print_operand_punct[]; extern int microblaze_section_threshold; /* Map register # to debug register # */ -extern int microblaze_dbx_regno[]; +extern int microblaze_debugger_regno[]; extern int microblaze_no_unsafe_delay; extern int microblaze_has_clz; @@ -163,8 +163,8 @@ extern enum pipeline_type microblaze_pipe; /* Debug stuff. */ -/* How to renumber registers for dbx and gdb. */ -#define DBX_REGISTER_NUMBER(REGNO) microblaze_dbx_regno[(REGNO)] +/* How to renumber registers for gdb. */ +#define DEBUGGER_REGNO(REGNO) microblaze_debugger_regno[(REGNO)] /* Generate DWARF exception handling info. */ #define DWARF2_UNWIND_INFO 1 @@ -276,7 +276,7 @@ extern enum pipeline_type microblaze_pipe; #define GP_REG_FIRST 0 #define GP_REG_LAST 31 #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) -#define GP_DBX_FIRST 0 +#define GP_DEBUGGER_FIRST 0 #define ST_REG 32 #define AP_REG_NUM 33 diff --git a/gcc/config/mips/mips-d.cc b/gcc/config/mips/mips-d.cc index 41a278a..8b6ccd1 100644 --- a/gcc/config/mips/mips-d.cc +++ b/gcc/config/mips/mips-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/mips/mips-d.h b/gcc/config/mips/mips-d.h new file mode 100644 index 0000000..7cb3ed9 --- /dev/null +++ b/gcc/config/mips/mips-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the MIPS architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Routines implemented in mips-d.cc */ +extern void mips_d_target_versions (void); +extern void mips_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS mips_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO mips_d_register_target_info diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 9d0f4d9..8635052 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -388,8 +388,4 @@ extern void mips_register_frame_header_opt (void); extern void mips_expand_vec_cond_expr (machine_mode, machine_mode, rtx *); extern void mips_expand_vec_cmp_expr (rtx *); -/* Routines implemented in mips-d.cc */ -extern void mips_d_target_versions (void); -extern void mips_d_register_target_info (void); - #endif /* ! GCC_MIPS_PROTOS_H */ diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index e81a245..4772495 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -445,7 +445,6 @@ int num_source_filenames; const char *current_function_file = ""; /* Arrays that map GCC register numbers to debugger register numbers. */ -int mips_dbx_regno[FIRST_PSEUDO_REGISTER]; int mips_dwarf_regno[FIRST_PSEUDO_REGISTER]; /* Information about the current function's epilogue, used only while @@ -9595,10 +9594,6 @@ mips_output_filename (FILE *stream, const char *name) output_quoted_string (stream, name); putc ('\n', stream); } - /* If we are emitting stabs, let dbxout.cc handle this (except for - the mips_output_filename_first_time case). */ - else if (write_symbols == DBX_DEBUG) - return; else if (name != current_function_file && strcmp (name, current_function_file) != 0) { @@ -20505,24 +20500,13 @@ mips_option_override (void) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { - mips_dbx_regno[i] = IGNORED_DWARF_REGNUM; if (GP_REG_P (i) || FP_REG_P (i) || ALL_COP_REG_P (i)) mips_dwarf_regno[i] = i; else mips_dwarf_regno[i] = INVALID_REGNUM; } - start = GP_DBX_FIRST - GP_REG_FIRST; - for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++) - mips_dbx_regno[i] = i + start; - - start = FP_DBX_FIRST - FP_REG_FIRST; - for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++) - mips_dbx_regno[i] = i + start; - /* Accumulator debug registers use big-endian ordering. */ - mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0; - mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1; mips_dwarf_regno[HI_REGNUM] = MD_REG_FIRST + 0; mips_dwarf_regno[LO_REGNUM] = MD_REG_FIRST + 1; for (i = DSP_ACC_REG_FIRST; i <= DSP_ACC_REG_LAST; i += 2) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 0029864..74b6e11 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -680,10 +680,6 @@ struct mips_cpu_info { } \ while (0) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS mips_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO mips_d_register_target_info - /* Default target_flags if no switches are specified */ #ifndef TARGET_DEFAULT @@ -1384,9 +1380,7 @@ struct mips_cpu_info { #ifndef SUBTARGET_ASM_DEBUGGING_SPEC #define SUBTARGET_ASM_DEBUGGING_SPEC "\ %{g} %{g0} %{g1} %{g2} %{g3} \ -%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \ -%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \ -%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3}" +%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3}" #endif /* FP_ASM_SPEC represents the floating-point options that must be passed @@ -1508,7 +1502,6 @@ FP_ASM_SPEC "\ #define SUBTARGET_EXTRA_SPECS #endif -#define DBX_DEBUGGING_INFO 1 /* generate stabs (OSF/rose) */ #define DWARF2_DEBUGGING_INFO 1 /* dwarf2 debugging info */ #ifndef PREFERRED_DEBUGGING_TYPE @@ -1548,14 +1541,6 @@ FP_ASM_SPEC "\ #define USER_LABEL_PREFIX "" #endif -/* On Sun 4, this limit is 2048. We use 1500 to be safe, - since the length can run past this up to a continuation point. */ -#undef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 1500 - -/* How to renumber registers for dbx and gdb. */ -#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[REGNO] - /* The mapping from gcc register number to DWARF 2 CFA column number. */ #define DWARF_FRAME_REGNUM(REGNO) mips_dwarf_regno[REGNO] @@ -1869,7 +1854,6 @@ FP_ASM_SPEC "\ #define GP_REG_FIRST 0 #define GP_REG_LAST 31 #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) -#define GP_DBX_FIRST 0 #define K0_REG_NUM (GP_REG_FIRST + 26) #define K1_REG_NUM (GP_REG_FIRST + 27) #define KERNEL_REG_P(REGNO) (IN_RANGE (REGNO, K0_REG_NUM, K1_REG_NUM)) @@ -1877,12 +1861,10 @@ FP_ASM_SPEC "\ #define FP_REG_FIRST 32 #define FP_REG_LAST 63 #define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1) -#define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32) #define MD_REG_FIRST 64 #define MD_REG_LAST 65 #define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1) -#define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM) #define MSA_REG_FIRST FP_REG_FIRST #define MSA_REG_LAST FP_REG_LAST @@ -3221,7 +3203,6 @@ extern int num_source_filenames; /* current .file # */ extern struct mips_asm_switch mips_noreorder; extern struct mips_asm_switch mips_nomacro; extern struct mips_asm_switch mips_noat; -extern int mips_dbx_regno[]; extern int mips_dwarf_regno[]; extern bool mips_split_p[]; extern bool mips_split_hi_p[]; diff --git a/gcc/config/mips/vxworks.h b/gcc/config/mips/vxworks.h index 11a71e0..3f24d6e 100644 --- a/gcc/config/mips/vxworks.h +++ b/gcc/config/mips/vxworks.h @@ -75,4 +75,4 @@ VXWORKS_LINK_SPEC #undef SUBTARGET_OVERRIDE_OPTIONS #define SUBTARGET_OVERRIDE_OPTIONS VXWORKS_OVERRIDE_OPTIONS -#undef DBX_REGISTER_NUMBER +#undef DEBUGGER_REGNO diff --git a/gcc/config/mmix/mmix-protos.h b/gcc/config/mmix/mmix-protos.h index d9a40d3..c5e6eb7 100644 --- a/gcc/config/mmix/mmix-protos.h +++ b/gcc/config/mmix/mmix-protos.h @@ -42,7 +42,7 @@ extern int mmix_shiftable_wyde_value (uint64_t); extern void mmix_output_register_setting (FILE *, int, int64_t, int); extern int mmix_opposite_regno (int, int); extern int mmix_local_regno (int); -extern unsigned mmix_dbx_register_number (unsigned); +extern unsigned mmix_debugger_regno (unsigned); extern int mmix_use_simple_return (void); extern void mmix_make_decl_one_only (tree); extern int mmix_data_alignment (tree, int); diff --git a/gcc/config/mmix/mmix.cc b/gcc/config/mmix/mmix.cc index 439ae8f..ffdd8c7 100644 --- a/gcc/config/mmix/mmix.cc +++ b/gcc/config/mmix/mmix.cc @@ -1942,10 +1942,10 @@ mmix_asm_output_align (FILE *stream, int power) fprintf (stream, "\tLOC @+(%d-@)&%d\n", 1 << power, (1 << power) - 1); } -/* DBX_REGISTER_NUMBER. */ +/* DEBUGGER_REGNO. */ unsigned -mmix_dbx_register_number (unsigned regno) +mmix_debugger_regno (unsigned regno) { /* Adjust the register number to the one it will be output as, dammit. It'd be nice if we could check the assumption that we're filling a @@ -1956,7 +1956,7 @@ mmix_dbx_register_number (unsigned regno) /* We need to renumber registers to get the number of the return address register in the range 0..255. It is also space-saving if registers mentioned in the call-frame information (which uses this function by - defaulting DWARF_FRAME_REGNUM to DBX_REGISTER_NUMBER) are numbered + defaulting DWARF_FRAME_REGNUM to DEBUGGER_REGNO) are numbered 0 .. 63. So map 224 .. 256+15 -> 0 .. 47 and 0 .. 223 -> 48..223+48. */ return regno >= 224 ? (regno - 224) : (regno + 48); } diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index 0fc45db..2896f63 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -757,17 +757,8 @@ typedef struct { int regs; int lib; } CUMULATIVE_ARGS; /* Node: All Debuggers */ -#define DBX_REGISTER_NUMBER(REGNO) \ - mmix_dbx_register_number (REGNO) - - -/* Node: DBX Options */ -/* (empty) */ -/* Node: DBX Hooks */ -/* (empty) */ -/* Node: File Names and DBX */ -/* (empty) */ - +#define DEBUGGER_REGNO(REGNO) \ + mmix_debugger_regno (REGNO) /* Node: DWARF */ #define DWARF2_DEBUGGING_INFO 1 diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index 377423c..0b44ee7 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -65,7 +65,7 @@ extern void nds32_emit_v3pop_fpr_callee_saved (int); /* Controlling Debugging Information Format. */ -extern unsigned int nds32_dbx_register_number (unsigned int); +extern unsigned int nds32_debugger_regno (unsigned int); /* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.cc b/gcc/config/nds32/nds32.cc index 71fe9e8..67a6121 100644 --- a/gcc/config/nds32/nds32.cc +++ b/gcc/config/nds32/nds32.cc @@ -3889,7 +3889,7 @@ nds32_dwarf_register_span (rtx reg) /* Map internal gcc register numbers to DWARF2 register numbers. */ unsigned int -nds32_dbx_register_number (unsigned int regno) +nds32_debugger_regno (unsigned int regno) { /* The nds32 port in GDB maintains a mapping between dwarf register number and displayed register name. For backward compatibility to @@ -5809,12 +5809,6 @@ nds32_use_blocks_for_constant_p (machine_mode mode, /* -- Macros Affecting All Debugging Formats. */ -/* -- Specific Options for DBX Output. */ - -/* -- Open-Ended Hooks for DBX Format. */ - -/* -- File Names in DBX Format. */ - /* -- Macros for DWARF Output. */ /* -- Macros for VMS Debug Format. */ diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h index 18ef8ae..cd00b2a 100644 --- a/gcc/config/nds32/nds32.h +++ b/gcc/config/nds32/nds32.h @@ -1332,7 +1332,7 @@ enum reg_class This is used to unwind the stack to an exception handler's call frame. */ #define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 2) -#define DBX_REGISTER_NUMBER(REGNO) nds32_dbx_register_number (REGNO) +#define DEBUGGER_REGNO(REGNO) nds32_debugger_regno (REGNO) #define STACK_POINTER_REGNUM SP_REGNUM diff --git a/gcc/config/netbsd-d.cc b/gcc/config/netbsd-d.cc index 286f010..cd0c955 100644 --- a/gcc/config/netbsd-d.cc +++ b/gcc/config/netbsd-d.cc @@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" -#include "memmodel.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index e4297e2..3634a49 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -52,7 +52,6 @@ #include "tm-preds.h" #include "tm-constrs.h" #include "langhooks.h" -#include "dbxout.h" #include "cfgrtl.h" #include "gimple.h" #include "stor-layout.h" diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index ed72c25..dc9cad1 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -253,7 +253,7 @@ struct GTY(()) machine_function #undef ASM_APP_OFF #define ASM_APP_OFF "\t// #NO_APP \n" -#define DBX_REGISTER_NUMBER(N) N +#define DEBUGGER_REGNO(N) N #define TEXT_SECTION_ASM_OP "" #define DATA_SECTION_ASM_OP "" @@ -321,6 +321,9 @@ struct GTY(()) machine_function #define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \ do \ { \ + (void) (FILE); \ + (void) (LABEL1); \ + (void) (LABEL2); \ gcc_unreachable (); \ } \ while (0) diff --git a/gcc/config/openbsd-d.cc b/gcc/config/openbsd-d.cc index c1a2a89..33c7e41 100644 --- a/gcc/config/openbsd-d.cc +++ b/gcc/config/openbsd-d.cc @@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "memmodel.h" -#include "tm.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h index 54be222..aa90ef7 100644 --- a/gcc/config/openbsd.h +++ b/gcc/config/openbsd.h @@ -151,17 +151,6 @@ while (0) #define TARGET_LIBC_HAS_FUNCTION default_libc_has_function -/* Runtime target specification. */ - -/* Miscellaneous parameters. */ - -/* Controlling debugging info: dbx options. */ - -/* Don't use the `xsTAG;' construct in DBX output; OpenBSD systems that - use DBX don't support it. */ -#define DBX_NO_XREFS - - /* - we use . - _func instead of a local label, - we put extra spaces in expressions such as .type _func , @function diff --git a/gcc/config/or1k/or1k.h b/gcc/config/or1k/or1k.h index 18a526d..c2decf3a 100644 --- a/gcc/config/or1k/or1k.h +++ b/gcc/config/or1k/or1k.h @@ -146,7 +146,7 @@ : (X) < 24 ? ((X) - 16) * 2 + 17 \ : ((X) - 24) * 2 + 16) -#define DBX_REGISTER_NUMBER(X) GCC_TO_HW_REGNO(X) +#define DEBUGGER_REGNO(X) GCC_TO_HW_REGNO(X) #define REGISTER_NAMES { \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ diff --git a/gcc/config/pa/pa-64.h b/gcc/config/pa/pa-64.h index bf50576..5157b7f3 100644 --- a/gcc/config/pa/pa-64.h +++ b/gcc/config/pa/pa-64.h @@ -65,10 +65,6 @@ along with GCC; see the file COPYING3. If not see #undef LONG_DOUBLE_TYPE_SIZE #define LONG_DOUBLE_TYPE_SIZE 128 -/* Temporary until we figure out what to do with those *(&@$ 32bit - relocs which appear in stabs. */ -#undef DBX_DEBUGGING_INFO - /* ?!? This needs to be made compile-time selectable. The PA64 runtime model has arguments that grow to higher addresses diff --git a/gcc/config/pa/pa-d.cc b/gcc/config/pa/pa-d.cc index 122ad48..077aeb5 100644 --- a/gcc/config/pa/pa-d.cc +++ b/gcc/config/pa/pa-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "target.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/pa/pa-d.h b/gcc/config/pa/pa-d.h new file mode 100644 index 0000000..9a9df10 --- /dev/null +++ b/gcc/config/pa/pa-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the HPPA architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Routines implemented in pa-d.cc */ +extern void pa_d_target_versions (void); +extern void pa_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS pa_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO pa_d_register_target_info diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h deleted file mode 100644 index 9297768..0000000 --- a/gcc/config/pa/pa-hpux10.h +++ /dev/null @@ -1,157 +0,0 @@ -/* Definitions of target machine for GNU compiler, for HP PA-RISC - Copyright (C) 1995-2022 Free Software Foundation, Inc. - Contributed by Tim Moore (moore@defmacro.cs.utah.edu) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* GCC always defines __STDC__. HP C++ compilers don't define it. This - causes trouble when sys/stdsyms.h is included. As a work around, - we define __STDC_EXT__. A similar situation exists with respect to - the definition of __cplusplus. We define _INCLUDE_LONGLONG - to prevent nlist.h from defining __STDC_32_MODE__ (no longlong - support). We define __STDCPP__ to get certain system headers - (notably assert.h) to assume standard preprocessor behavior in C++. - We define _XOPEN_SOURCE_EXTENDED when we define _HPUX_SOURCE to avoid - non standard hpux variants in _INCLUDE_XOPEN_SOURCE_EXTENDED. */ -#undef TARGET_OS_CPP_BUILTINS -#define TARGET_OS_CPP_BUILTINS() \ - do \ - { \ - builtin_assert ("system=hpux"); \ - builtin_assert ("system=unix"); \ - builtin_define ("__hp9000s800"); \ - builtin_define ("__hp9000s800__"); \ - builtin_define ("__hpux"); \ - builtin_define ("__hpux__"); \ - builtin_define ("__unix"); \ - builtin_define ("__unix__"); \ - builtin_define ("__STDC_EXT__"); \ - if (c_dialect_cxx ()) \ - { \ - builtin_define ("_HPUX_SOURCE"); \ - builtin_define ("_REENTRANT"); \ - builtin_define ("_INCLUDE_LONGLONG"); \ - builtin_define ("__STDCPP__"); \ - builtin_define ("_LARGEFILE_SOURCE"); \ - builtin_define ("_LARGEFILE64_SOURCE"); \ - if (flag_pa_unix >= 1995) \ - { \ - builtin_define ("_XOPEN_UNIX"); \ - builtin_define ("_XOPEN_SOURCE_EXTENDED"); \ - } \ - } \ - else if (flag_iso) \ - { \ - if (flag_isoc94) \ - builtin_define ("_INCLUDE__STDC_A1_SOURCE"); \ - } \ - else \ - { \ - builtin_define ("_HPUX_SOURCE"); \ - builtin_define ("_REENTRANT"); \ - if (preprocessing_trad_p ()) \ - { \ - builtin_define ("hp9000s800"); \ - builtin_define ("hppa"); \ - builtin_define ("hpux"); \ - builtin_define ("unix"); \ - builtin_define ("__CLASSIC_C__"); \ - builtin_define ("_PWB"); \ - builtin_define ("PWB"); \ - } \ - if (flag_pa_unix >= 1995) \ - { \ - builtin_define ("_XOPEN_UNIX"); \ - builtin_define ("_XOPEN_SOURCE_EXTENDED"); \ - } \ - } \ - if (TARGET_SIO) \ - builtin_define ("_SIO"); \ - else \ - { \ - builtin_define ("__hp9000s700"); \ - builtin_define ("__hp9000s700__"); \ - builtin_define ("_WSIO"); \ - } \ - } \ - while (0) - -#define CPP_SPEC "%{threads: -D_REENTRANT -D_DCE_THREADS}" - -/* We can debug dynamically linked executables on hpux9; we also want - dereferencing of a NULL pointer to cause a SEGV. */ -#undef LINK_SPEC -#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11) -#define LINK_SPEC \ - "%{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\ - %{!shared:%{p:-L/lib/libp %{!static:\ - %nwarning: consider linking with '-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - %{!shared:%{pg:-L/lib/libp %{!static:\ - %nwarning: consider linking with '-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - %{!shared:%{!static:%{rdynamic:-E}}}\ - -z %{mlinker-opt:-O} %{!shared:-u main}\ - %{static:-a archive} %{shared:-b}" -#else -#define LINK_SPEC \ - "%{!shared:%{p:-L/lib/libp %{!static:\ - %nwarning: consider linking with '-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - %{!shared:%{pg:-L/lib/libp %{!static:\ - %nwarning: consider linking with '-static' as system libraries with\n\ - %n profiling support are only provided in archive format}}}\ - %{!shared:%{!static:%{rdynamic:-E}}}\ - -z %{mlinker-opt:-O} %{!shared:-u main}\ - %{static:-a archive} %{shared:-b}" -#endif - -/* Like the default, except no -lg. */ -#undef LIB_SPEC -#define LIB_SPEC \ - "%{!shared:\ - %{!p:%{!pg:\ - %{!threads:-lc %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}\ - %{threads:-lcma -lc}}}\ - %{p:%{!pg:-lc %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}\ - %{pg:-lc %{static:%{!nolibdld:-a shared -ldld -a archive -lc}}}}" - -#undef THREAD_MODEL_SPEC -#define THREAD_MODEL_SPEC "%{!threads:single}%{threads:dce}" - -/* Under hpux10, the normal location of the `ld' and `as' programs is the - /usr/ccs/bin directory. */ - -#ifndef CROSS_DIRECTORY_STRUCTURE -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/ccs/bin/" -#endif - -/* Under hpux10, the normal location of the various *crt*.o files is - the /usr/ccs/lib directory. However, the profiling files are in - /opt/langtools/lib. */ - -#ifndef CROSS_DIRECTORY_STRUCTURE -#undef MD_STARTFILE_PREFIX -#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" -#define MD_STARTFILE_PREFIX_1 "/opt/langtools/lib/" -#endif - -/* hpux10 has the new HP assembler. It's still lousy, but it's a whole lot - better than the assembler shipped with older versions of hpux. */ -#undef NEW_HP_ASSEMBLER -#define NEW_HP_ASSEMBLER 1 diff --git a/gcc/config/pa/pa-hpux10.opt b/gcc/config/pa/pa-hpux10.opt deleted file mode 100644 index d7e639a..0000000 --- a/gcc/config/pa/pa-hpux10.opt +++ /dev/null @@ -1,22 +0,0 @@ -; Options specific to HP-UX 10. - -; Copyright (C) 2011-2022 Free Software Foundation, Inc. -; -; This file is part of GCC. -; -; GCC is free software; you can redistribute it and/or modify it under -; the terms of the GNU General Public License as published by the Free -; Software Foundation; either version 3, or (at your option) any later -; version. -; -; GCC is distributed in the hope that it will be useful, but WITHOUT ANY -; WARRANTY; without even the implied warranty of MERCHANTABILITY or -; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -; for more details. -; -; You should have received a copy of the GNU General Public License -; along with GCC; see the file COPYING3. If not see -; <http://www.gnu.org/licenses/>. - -threads -Driver diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index d474d9e..fe8b7a5 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -111,7 +111,3 @@ extern void pa_output_function_label (FILE *); extern void hppa_profile_hook (int); extern const int pa_magic_milli[]; - -/* Routines implemented in pa-d.cc */ -extern void pa_d_target_versions (void); -extern void pa_d_register_target_info (void); diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 92d3d18..bafdf60 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -130,8 +130,6 @@ extern unsigned long total_code_bytes; and the old mnemonics are dialect zero. */ #define ASSEMBLER_DIALECT (TARGET_PA_20 ? 1 : 0) -/* Override some settings from dbxelf.h. */ - /* We do not have to be compatible with dbx, so we enable gdb extensions by default. */ #define DEFAULT_GDB_EXTENSIONS 1 @@ -139,14 +137,6 @@ extern unsigned long total_code_bytes; /* Select dwarf2 as the preferred debug format. */ #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -/* This used to be zero (no max length), but big enums and such can - cause huge strings which killed gas. - - We also have to avoid lossage in dbxout.cc -- it does not compute the - string size accurately, so we are real conservative here. */ -#undef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 3000 - /* GDB always assumes the current function's frame begins at the value of the stack pointer upon entry to the current function. Accessing local variables and parameters passed on the stack is done using the @@ -1310,9 +1300,5 @@ do { \ #define NEED_INDICATE_EXEC_STACK 0 -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS pa_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO pa_d_register_target_info - /* Output default function prologue for hpux. */ #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue diff --git a/gcc/config/pa/pa32-regs.h b/gcc/config/pa/pa32-regs.h index 62084a5..1d511aa 100644 --- a/gcc/config/pa/pa32-regs.h +++ b/gcc/config/pa/pa32-regs.h @@ -227,7 +227,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see || (GET_MODE_SIZE (MODE) == 8 * UNITS_PER_WORD \ && ((REGNO) & 7) == 3 && (REGNO) <= 19))) -/* How to renumber registers for dbx and gdb. +/* How to renumber registers for gdb. Registers 0 - 31 remain unchanged. @@ -235,11 +235,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see Register 88 is mapped to 32. */ -#define DBX_REGISTER_NUMBER(REGNO) \ +#define DEBUGGER_REGNO(REGNO) \ ((REGNO) <= 31 ? (REGNO) : \ ((REGNO) <= 87 ? (REGNO) + 40 : 32)) -/* We must not use the DBX register numbers for the DWARF 2 CFA column +/* We must not use the debugger register numbers for the DWARF 2 CFA column numbers because that maps to numbers beyond FIRST_PSEUDO_REGISTER. Instead use the identity mapping. */ #define DWARF_FRAME_REGNUM(REG) REG diff --git a/gcc/config/pa/pa64-regs.h b/gcc/config/pa/pa64-regs.h index 7daf445..02b76e0e 100644 --- a/gcc/config/pa/pa64-regs.h +++ b/gcc/config/pa/pa64-regs.h @@ -165,17 +165,17 @@ along with GCC; see the file COPYING3. If not see || (GET_MODE_SIZE (MODE) == 4 * UNITS_PER_WORD \ && ((REGNO) & 3) == 3 && (REGNO) <= 23))) -/* How to renumber registers for dbx and gdb. +/* How to renumber registers for gdb. Registers 0 - 31 remain unchanged. Registers 32 - 59 are mapped to 72, 74, 76 ... Register 60 is mapped to 32. */ -#define DBX_REGISTER_NUMBER(REGNO) \ +#define DEBUGGER_REGNO(REGNO) \ ((REGNO) <= 31 ? (REGNO) : ((REGNO) < 60 ? (REGNO - 32) * 2 + 72 : 32)) -/* We must not use the DBX register numbers for the DWARF 2 CFA column +/* We must not use the debugger register numbers for the DWARF 2 CFA column numbers because that maps to numbers beyond FIRST_PSEUDO_REGISTER. Instead use the identity mapping. */ #define DWARF_FRAME_REGNUM(REG) REG diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h index d2510e9..3efae0e 100644 --- a/gcc/config/pa/som.h +++ b/gcc/config/pa/som.h @@ -21,21 +21,6 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_SOM #define TARGET_SOM 1 -/* With SOM we can only do STABS. */ -#undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG - -/* We do not use BINCL stabs in SOM. - ??? If it does not hurt, we probably should to avoid useless divergence - from other embedded stabs implementations. */ -#undef DBX_USE_BINCL - -#define DBX_LINES_FUNCTION_RELATIVE 1 - -/* gdb needs a null N_SO at the end of each file for scattered loading. */ - -#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - /* HPUX has a program 'chatr' to list the dependencies of dynamically linked executables and shared libraries. */ #define LDD_SUFFIX "chatr" diff --git a/gcc/config/pa/t-dce-thr b/gcc/config/pa/t-dce-thr deleted file mode 100644 index 51b3abc..0000000 --- a/gcc/config/pa/t-dce-thr +++ /dev/null @@ -1,2 +0,0 @@ -MULTILIB_OPTIONS = threads -MULTILIB_DIRNAMES = threads diff --git a/gcc/config/pdp11/pdp11.cc b/gcc/config/pdp11/pdp11.cc index f7482df..3802234 100644 --- a/gcc/config/pdp11/pdp11.cc +++ b/gcc/config/pdp11/pdp11.cc @@ -44,7 +44,6 @@ along with GCC; see the file COPYING3. If not see #include "calls.h" #include "expr.h" #include "builtins.h" -#include "dbxout.h" #include "explow.h" #include "expmed.h" diff --git a/gcc/config/pdp11/pdp11.h b/gcc/config/pdp11/pdp11.h index b7d66c3..d783b36 100644 --- a/gcc/config/pdp11/pdp11.h +++ b/gcc/config/pdp11/pdp11.h @@ -49,13 +49,8 @@ along with GCC; see the file COPYING3. If not see } \ while (0) - -/* Generate DBX debugging information. */ - -#define DBX_DEBUGGING_INFO - #undef PREFERRED_DEBUGGING_TYPE -#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#define PREFERRED_DEBUGGING_TYPE NO_DEBUG #define TARGET_40_PLUS (TARGET_40 || TARGET_45) #define TARGET_10 (! TARGET_40_PLUS) @@ -489,9 +484,6 @@ extern int current_first_parm_offset; /* Nonzero if access to memory by byte is no faster than by word. */ #define SLOW_BYTE_ACCESS 1 -/* Do not break .stabs pseudos into continuations. */ -#define DBX_CONTIN_LENGTH 0 - /* Give a comparison code (EQ, NE etc) and the first operand of a COMPARE, return the mode to be used for the comparison. */ diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index d1570ce..b44fb95 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -17,31 +17,6 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. -(define_code_iterator bitmanip_bitwise [and ior]) - -(define_code_iterator bitmanip_minmax [smin umin smax umax]) - -(define_code_iterator clz_ctz_pcnt [clz ctz popcount]) - -(define_code_attr bitmanip_optab [(smin "smin") - (smax "smax") - (umin "umin") - (umax "umax") - (clz "clz") - (ctz "ctz") - (popcount "popcount")]) - - -(define_code_attr bitmanip_insn [(smin "min") - (smax "max") - (umin "minu") - (umax "maxu") - (clz "clz") - (ctz "ctz") - (popcount "cpop")]) - -(define_mode_attr shiftm1 [(SI "const31_operand") (DI "const63_operand")]) - ;; ZBA extension. (define_insn "*zero_extendsidi2_bitmanip" @@ -57,10 +32,9 @@ (define_insn "*shNadd" [(set (match_operand:X 0 "register_operand" "=r") (plus:X (ashift:X (match_operand:X 1 "register_operand" "r") - (match_operand:QI 2 "immediate_operand" "I")) + (match_operand:QI 2 "imm123_operand" "Ds3")) (match_operand:X 3 "register_operand" "r")))] - "TARGET_ZBA - && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3)" + "TARGET_ZBA" "sh%2add\t%0,%1,%3" [(set_attr "type" "bitmanip") (set_attr "mode" "<X:MODE>")]) @@ -69,11 +43,10 @@ [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") - (match_operand:QI 2 "immediate_operand" "I")) - (match_operand 3 "immediate_operand" "")) + (match_operand:QI 2 "imm123_operand" "Ds3")) + (match_operand 3 "immediate_operand" "n")) (match_operand:DI 4 "register_operand" "r")))] "TARGET_64BIT && TARGET_ZBA - && (INTVAL (operands[2]) >= 1) && (INTVAL (operands[2]) <= 3) && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff" "sh%2add.uw\t%0,%1,%4" [(set_attr "type" "bitmanip") @@ -137,7 +110,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r") (match_operand:QI 2 "immediate_operand" "I")) - (match_operand 3 "immediate_operand" "")))] + (match_operand 3 "immediate_operand" "n")))] "TARGET_64BIT && TARGET_ZBA && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff" "slli.uw\t%0,%1,%2" @@ -168,7 +141,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))] "TARGET_ZBB" - { return TARGET_64BIT ? "<bitmanip_insn>w\t%0,%1" : "<bitmanip_insn>\t%0,%1"; } + "<bitmanip_insn>%~\t%0,%1" [(set_attr "type" "bitmanip") (set_attr "mode" "SI")]) @@ -226,7 +199,7 @@ (rotatert:SI (match_operand:SI 1 "register_operand" "r") (match_operand:QI 2 "arith_operand" "rI")))] "TARGET_ZBB" - { return TARGET_64BIT ? "ror%i2w\t%0,%1,%2" : "ror%i2\t%0,%1,%2"; } + "ror%i2%~\t%0,%1,%2" [(set_attr "type" "bitmanip")]) (define_insn "rotrdi3" @@ -250,7 +223,7 @@ (rotate:SI (match_operand:SI 1 "register_operand" "r") (match_operand:QI 2 "register_operand" "r")))] "TARGET_ZBB" - { return TARGET_64BIT ? "rolw\t%0,%1,%2" : "rol\t%0,%1,%2"; } + "rol%~\t%0,%1,%2" [(set_attr "type" "bitmanip")]) (define_insn "rotldi3" @@ -272,10 +245,34 @@ (define_insn "bswap<mode>2" [(set (match_operand:X 0 "register_operand" "=r") (bswap:X (match_operand:X 1 "register_operand" "r")))] - "TARGET_64BIT && TARGET_ZBB" + "TARGET_ZBB" "rev8\t%0,%1" [(set_attr "type" "bitmanip")]) +;; HI bswap can be emulated using SI/DI bswap followed +;; by a logical shift right +;; SI bswap for TARGET_64BIT is already similarly in +;; the common code. +(define_expand "bswaphi2" + [(set (match_operand:HI 0 "register_operand" "=r") + (bswap:HI (match_operand:HI 1 "register_operand" "r")))] + "TARGET_ZBB" +{ + rtx tmp = gen_reg_rtx (word_mode); + rtx newop1 = gen_lowpart (word_mode, operands[1]); + if (TARGET_64BIT) + emit_insn (gen_bswapdi2 (tmp, newop1)); + else + emit_insn (gen_bswapsi2 (tmp, newop1)); + rtx tmp1 = gen_reg_rtx (word_mode); + if (TARGET_64BIT) + emit_insn (gen_lshrdi3 (tmp1, tmp, GEN_INT (64 - 16))); + else + emit_insn (gen_lshrsi3 (tmp1, tmp, GEN_INT (32 - 16))); + emit_move_insn (operands[0], gen_lowpart (HImode, tmp1)); + DONE; +}) + (define_insn "<bitmanip_optab><mode>3" [(set (match_operand:X 0 "register_operand" "=r") (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r") @@ -300,7 +297,7 @@ (ior:X (ashift:X (const_int 1) (subreg:QI (and:X (match_operand:X 2 "register_operand" "r") - (match_operand 3 "<X:shiftm1>" "i")) 0)) + (match_operand 3 "<X:shiftm1>" "<X:shiftm1p>")) 0)) (match_operand:X 1 "register_operand" "r")))] "TARGET_ZBS" "bset\t%0,%1,%2" @@ -319,7 +316,7 @@ (ashift:X (const_int 1) (subreg:QI (and:X (match_operand:X 1 "register_operand" "r") - (match_operand 2 "<X:shiftm1>" "i")) 0)))] + (match_operand 2 "<X:shiftm1>" "<X:shiftm1p>")) 0)))] "TARGET_ZBS" "bset\t%0,x0,%1" [(set_attr "type" "bitmanip")]) @@ -327,7 +324,7 @@ (define_insn "*bseti<mode>" [(set (match_operand:X 0 "register_operand" "=r") (ior:X (match_operand:X 1 "register_operand" "r") - (match_operand 2 "single_bit_mask_operand" "i")))] + (match_operand:X 2 "single_bit_mask_operand" "DbS")))] "TARGET_ZBS" "bseti\t%0,%1,%S2" [(set_attr "type" "bitmanip")]) @@ -344,7 +341,7 @@ (define_insn "*bclri<mode>" [(set (match_operand:X 0 "register_operand" "=r") (and:X (match_operand:X 1 "register_operand" "r") - (match_operand 2 "not_single_bit_mask_operand" "i")))] + (match_operand:X 2 "not_single_bit_mask_operand" "DnS")))] "TARGET_ZBS" "bclri\t%0,%1,%T2" [(set_attr "type" "bitmanip")]) @@ -361,7 +358,7 @@ (define_insn "*binvi<mode>" [(set (match_operand:X 0 "register_operand" "=r") (xor:X (match_operand:X 1 "register_operand" "r") - (match_operand 2 "single_bit_mask_operand" "i")))] + (match_operand:X 2 "single_bit_mask_operand" "DbS")))] "TARGET_ZBS" "binvi\t%0,%1,%S2" [(set_attr "type" "bitmanip")]) @@ -380,7 +377,7 @@ [(set (match_operand:X 0 "register_operand" "=r") (zero_extract:X (match_operand:X 1 "register_operand" "r") (const_int 1) - (match_operand 2 "immediate_operand" "i")))] - "TARGET_ZBS" + (match_operand 2 "immediate_operand" "n")))] + "TARGET_ZBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" "bexti\t%0,%1,%2" [(set_attr "type" "bitmanip")]) diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index bafa418..8997284 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -54,6 +54,34 @@ (and (match_code "const_int") (match_test "LUI_OPERAND (ival)"))) +(define_constraint "Ds3" + "@internal + 1, 2 or 3 immediate" + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 1, 3)"))) + +(define_constraint "DsS" + "@internal + 31 immediate" + (and (match_code "const_int") + (match_test "ival == 31"))) + +(define_constraint "DsD" + "@internal + 63 immediate" + (and (match_code "const_int") + (match_test "ival == 63"))) + +(define_constraint "DbS" + "@internal" + (and (match_code "const_int") + (match_test "SINGLE_BIT_MASK_OPERAND (ival)"))) + +(define_constraint "DnS" + "@internal" + (and (match_code "const_int") + (match_test "SINGLE_BIT_MASK_OPERAND (~ival)"))) + ;; Floating-point constant +0.0, used for FCVT-based moves when FMV is ;; not available in RV32. (define_constraint "G" @@ -80,3 +108,23 @@ A constant @code{move_operand}." (and (match_operand 0 "move_operand") (match_test "CONSTANT_P (op)"))) + +;; Vector constraints. + +(define_register_constraint "vr" "TARGET_VECTOR ? V_REGS : NO_REGS" + "A vector register (if available).") + +(define_register_constraint "vd" "TARGET_VECTOR ? VD_REGS : NO_REGS" + "A vector register except mask register (if available).") + +(define_register_constraint "vm" "TARGET_VECTOR ? VM_REGS : NO_REGS" + "A vector mask register (if available).") + +;; This constraint is used to match instruction "csrr %0, vlenb" which is generated in "mov<mode>". +;; VLENB is a run-time constant which represent the vector register length in bytes. +;; BYTES_PER_RISCV_VECTOR represent runtime invariant of vector register length in bytes. +;; We should only allow the poly equal to BYTES_PER_RISCV_VECTOR. +(define_constraint "vp" + "POLY_INT" + (and (match_code "const_poly_int") + (match_test "known_eq (rtx_to_poly_int64 (op), BYTES_PER_RISCV_VECTOR)"))) diff --git a/gcc/config/riscv/elf.h b/gcc/config/riscv/elf.h index f0e865d..f3d767c 100644 --- a/gcc/config/riscv/elf.h +++ b/gcc/config/riscv/elf.h @@ -27,10 +27,14 @@ along with GCC; see the file COPYING3. If not see /* Link against Newlib libraries, because the ELF backend assumes Newlib. Handle the circular dependence between libc and libgloss. */ #undef LIB_SPEC -#define LIB_SPEC "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group" +#define LIB_SPEC \ + "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group " \ + "%{!nostartfiles:%{!nodefaultlibs:%{!nolibc:%{!nostdlib:%:riscv_multi_lib_check()}}}}" #undef STARTFILE_SPEC #define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" #undef ENDFILE_SPEC #define ENDFILE_SPEC "crtend%O%s" + +#define RISCV_USE_CUSTOMISED_MULTI_LIB 1 diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md new file mode 100644 index 0000000..39dffab --- /dev/null +++ b/gcc/config/riscv/iterators.md @@ -0,0 +1,244 @@ +;; Iterators for the machine description for RISC-V +;; Copyright (C) 2011-2022 Free Software Foundation, Inc. + +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + + +;; ------------------------------------------------------------------- +;; Mode Iterators +;; ------------------------------------------------------------------- + +;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated +;; from the same template. +(define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) + +;; This mode iterator allows :P to be used for patterns that operate on +;; pointer-sized quantities. Exactly one of the two alternatives will match. +(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) + +;; Likewise, but for XLEN-sized quantities. +(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) + +;; Branches operate on XLEN-sized quantities, but for RV64 we accept +;; QImode values so we can force zero-extension. +(define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")]) + +;; 32-bit moves for which we provide move patterns. +(define_mode_iterator MOVE32 [SI]) + +;; 64-bit modes for which we provide move patterns. +(define_mode_iterator MOVE64 [DI DF]) + +;; Iterator for sub-32-bit integer modes. +(define_mode_iterator SHORT [QI HI]) + +;; Iterator for HImode constant generation. +(define_mode_iterator HISI [HI SI]) + +;; Iterator for QImode extension patterns. +(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) + +;; Iterator for hardware integer modes narrower than XLEN. +(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) + +;; Iterator for hardware-supported integer modes. +(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) + +;; Iterator for hardware-supported floating-point modes. +(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") + (DF "TARGET_DOUBLE_FLOAT") + (HF "TARGET_ZFH")]) + +;; Iterator for floating-point modes that can be loaded into X registers. +(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) + + +;; ------------------------------------------------------------------- +;; Mode attributes +;; ------------------------------------------------------------------- + +;; This attribute gives the length suffix for a sign- or zero-extension +;; instruction. +(define_mode_attr size [(QI "b") (HI "h")]) + +;; Mode attributes for loads. +(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")]) + +;; Instruction names for integer loads that aren't explicitly sign or zero +;; extended. See riscv_output_move and LOAD_EXTEND_OP. +(define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")]) + +;; Mode attribute for FP loads into integer registers. +(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) + +;; Instruction names for stores. +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")]) + +;; Instruction names for FP stores from integer registers. +(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) + +;; This attribute gives the best constraint to use for registers of +;; a given mode. +(define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) + +;; This attribute gives the format suffix for floating-point operations. +(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")]) + +;; This attribute gives the integer suffix for floating-point conversions. +(define_mode_attr ifmt [(SI "w") (DI "l")]) + +;; This attribute gives the format suffix for atomic memory operations. +(define_mode_attr amo [(SI "w") (DI "d")]) + +;; This attribute gives the upper-case mode name for one unit of a +;; floating-point mode. +(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")]) + +;; This attribute gives the integer mode that has half the size of +;; the controlling mode. +(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) + +; bitmanip mode attribute +(define_mode_attr shiftm1 [(SI "const31_operand") (DI "const63_operand")]) +(define_mode_attr shiftm1p [(SI "DsS") (DI "DsD")]) + +;; ------------------------------------------------------------------- +;; Code Iterators +;; ------------------------------------------------------------------- + +;; This code iterator allows signed and unsigned widening multiplications +;; to use the same template. +(define_code_iterator any_extend [sign_extend zero_extend]) + +;; This code iterator allows the two right shift instructions to be +;; generated from the same template. +(define_code_iterator any_shiftrt [ashiftrt lshiftrt]) + +;; This code iterator allows the three shift instructions to be generated +;; from the same template. +(define_code_iterator any_shift [ashift ashiftrt lshiftrt]) + +;; This code iterator allows the three bitwise instructions to be generated +;; from the same template. +(define_code_iterator any_bitwise [and ior xor]) + +;; This code iterator allows unsigned and signed division to be generated +;; from the same template. +(define_code_iterator any_div [div udiv mod umod]) + +;; This code iterator allows unsigned and signed modulus to be generated +;; from the same template. +(define_code_iterator any_mod [mod umod]) + +;; These code iterators allow the signed and unsigned scc operations to use +;; the same template. +(define_code_iterator any_gt [gt gtu]) +(define_code_iterator any_ge [ge geu]) +(define_code_iterator any_lt [lt ltu]) +(define_code_iterator any_le [le leu]) + +; atomics code iterator +(define_code_iterator any_atomic [plus ior xor and]) + +; bitmanip code iterators +(define_code_iterator bitmanip_bitwise [and ior]) + +(define_code_iterator bitmanip_minmax [smin umin smax umax]) + +(define_code_iterator clz_ctz_pcnt [clz ctz popcount]) + +;; ------------------------------------------------------------------- +;; Code Attributes +;; ------------------------------------------------------------------- + +;; <u> expands to an empty string when doing a signed operation and +;; "u" when doing an unsigned operation. +(define_code_attr u [(sign_extend "") (zero_extend "u") + (gt "") (gtu "u") + (ge "") (geu "u") + (lt "") (ltu "u") + (le "") (leu "u")]) + +;; <su> is like <u>, but the signed form expands to "s" rather than "". +(define_code_attr su [(sign_extend "s") (zero_extend "u")]) + +;; <optab> expands to the name of the optab for a particular code. +(define_code_attr optab [(ashift "ashl") + (ashiftrt "ashr") + (lshiftrt "lshr") + (div "div") + (mod "mod") + (udiv "udiv") + (umod "umod") + (ge "ge") + (le "le") + (gt "gt") + (lt "lt") + (ior "ior") + (xor "xor") + (and "and") + (plus "add") + (minus "sub")]) + +;; <insn> expands to the name of the insn that implements a particular code. +(define_code_attr insn [(ashift "sll") + (ashiftrt "sra") + (lshiftrt "srl") + (div "div") + (mod "rem") + (udiv "divu") + (umod "remu") + (ior "or") + (xor "xor") + (and "and") + (plus "add") + (minus "sub")]) + +; atomics code attribute +(define_code_attr atomic_optab + [(plus "add") (ior "or") (xor "xor") (and "and")]) + +; bitmanip code attributes +(define_code_attr bitmanip_optab [(smin "smin") + (smax "smax") + (umin "umin") + (umax "umax") + (clz "clz") + (ctz "ctz") + (popcount "popcount")]) +(define_code_attr bitmanip_insn [(smin "min") + (smax "max") + (umin "minu") + (umax "maxu") + (clz "clz") + (ctz "ctz") + (popcount "cpop")]) + +;; ------------------------------------------------------------------- +;; Int Iterators. +;; ------------------------------------------------------------------- + +;; Iterator and attributes for floating-point rounding instructions. +(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND]) +(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")]) +(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")]) + +;; Iterator and attributes for quiet comparisons. +(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) +(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) +(define_int_attr QUIET_PATTERN [(UNSPEC_FLT_QUIET "LT") (UNSPEC_FLE_QUIET "LE")]) + diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 79e0c1d..862e72b 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -226,11 +226,11 @@ ;; Predicates for the ZBS extension. (define_predicate "single_bit_mask_operand" (and (match_code "const_int") - (match_test "pow2p_hwi (INTVAL (op))"))) + (match_test "SINGLE_BIT_MASK_OPERAND (UINTVAL (op))"))) (define_predicate "not_single_bit_mask_operand" (and (match_code "const_int") - (match_test "pow2p_hwi (~INTVAL (op))"))) + (match_test "SINGLE_BIT_MASK_OPERAND (~UINTVAL (op))"))) (define_predicate "const31_operand" (and (match_code "const_int") @@ -244,6 +244,11 @@ (and (match_code "const_int") (match_test "INTVAL (op) < 5"))) +;; A const_int for sh1add/sh2add/sh3add +(define_predicate "imm123_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 1, 3)"))) + ;; A CONST_INT operand that consists of a single run of consecutive set bits. (define_predicate "consecutive_bits_operand" (match_code "const_int") diff --git a/gcc/config/riscv/riscv-d.cc b/gcc/config/riscv/riscv-d.cc index 729de96..a762a35 100644 --- a/gcc/config/riscv/riscv-d.cc +++ b/gcc/config/riscv/riscv-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "target.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/riscv/riscv-d.h b/gcc/config/riscv/riscv-d.h new file mode 100644 index 0000000..21a989e --- /dev/null +++ b/gcc/config/riscv/riscv-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the RISC-V architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Routines implemented in riscv-d.cc */ +extern void riscv_d_target_versions (void); +extern void riscv_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS riscv_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO riscv_d_register_target_info diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 2bc0ef0..649c5c9 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -78,10 +78,6 @@ extern bool riscv_gpr_save_operation_p (rtx); /* Routines implemented in riscv-c.cc. */ void riscv_cpu_cpp_builtins (cpp_reader *); -/* Routines implemented in riscv-d.cc */ -extern void riscv_d_target_versions (void); -extern void riscv_d_register_target_info (void); - /* Routines implemented in riscv-builtins.cc. */ extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *); extern rtx riscv_expand_builtin (tree, rtx, rtx, machine_mode, int); diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h index c592650..0bb3a9d 100644 --- a/gcc/config/riscv/riscv-subset.h +++ b/gcc/config/riscv/riscv-subset.h @@ -89,6 +89,8 @@ public: const riscv_subset_t *begin () const {return m_head;}; const riscv_subset_t *end () const {return NULL;}; + + int match_score (riscv_subset_list *) const; }; extern const riscv_subset_list *riscv_current_subset_list (void); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 7c120ea..675d92c 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -123,6 +123,9 @@ struct GTY(()) riscv_frame_info { /* The offset of arg_pointer_rtx from the bottom of the frame. */ poly_int64 arg_pointer_offset; + + /* Reset this struct, clean all field to zero. */ + void reset(void); }; enum riscv_privilege_levels { @@ -279,7 +282,22 @@ const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, - FRAME_REGS, FRAME_REGS, + FRAME_REGS, FRAME_REGS, VL_REGS, VTYPE_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + NO_REGS, NO_REGS, NO_REGS, NO_REGS, + VM_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, + VD_REGS, VD_REGS, VD_REGS, VD_REGS, }; /* Costs to use when optimizing for rocket. */ @@ -377,6 +395,23 @@ static const struct riscv_tune_info riscv_tune_info_table[] = { { "size", generic, &optimize_size_tune_info }, }; +void riscv_frame_info::reset(void) +{ + total_size = 0; + mask = 0; + fmask = 0; + save_libcall_adjustment = 0; + + gp_sp_offset = 0; + fp_sp_offset = 0; + + frame_pointer_offset = 0; + + hard_frame_pointer_offset = 0; + + arg_pointer_offset = 0; +} + /* Implement TARGET_MIN_ARITHMETIC_PRECISION. */ static unsigned int @@ -432,7 +467,7 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS], sign-extended (negative) representation (-1 << 31) for the value, if we want to build (1 << 31) in SImode. This will then expand to an LUI instruction. */ - if (mode == SImode && value == (HOST_WIDE_INT_1U << 31)) + if (TARGET_64BIT && mode == SImode && value == (HOST_WIDE_INT_1U << 31)) codes[0].value = (HOST_WIDE_INT_M1U << 31); return 1; @@ -445,7 +480,11 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS], && (mode != HImode || value - low_part <= ((1 << (GET_MODE_BITSIZE (HImode) - 1)) - 1))) { - alt_cost = 1 + riscv_build_integer_1 (alt_codes, value - low_part, mode); + HOST_WIDE_INT upper_part = value - low_part; + if (mode != VOIDmode) + upper_part = trunc_int_for_mode (value - low_part, mode); + + alt_cost = 1 + riscv_build_integer_1 (alt_codes, upper_part, mode); if (alt_cost < cost) { alt_codes[alt_cost-1].code = PLUS; @@ -890,6 +929,14 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode, return true; } +/* Return true if mode is the RVV mode. */ + +static bool +riscv_v_ext_vector_mode_p (machine_mode mode) +{ + return VECTOR_MODE_P (mode); +} + /* Return true if X is a valid address for machine mode MODE. If it is, fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in effect. */ @@ -908,6 +955,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x, return riscv_valid_base_register_p (info->reg, mode, strict_p); case PLUS: + /* RVV load/store disallow any offset. */ + if (riscv_v_ext_vector_mode_p (mode)) + return false; + info->type = ADDRESS_REG; info->reg = XEXP (x, 0); info->offset = XEXP (x, 1); @@ -915,6 +966,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x, && riscv_valid_offset_p (info->offset, mode)); case LO_SUM: + /* RVV load/store disallow LO_SUM. */ + if (riscv_v_ext_vector_mode_p (mode)) + return false; + info->type = ADDRESS_LO_SUM; info->reg = XEXP (x, 0); info->offset = XEXP (x, 1); @@ -933,6 +988,10 @@ riscv_classify_address (struct riscv_address_info *info, rtx x, && riscv_valid_lo_sum_p (info->symbol_type, mode, info->offset)); case CONST_INT: + /* RVV load/store disallow CONST_INT. */ + if (riscv_v_ext_vector_mode_p (mode)) + return false; + /* Small-integer addresses don't occur very often, but they are legitimate if x0 is a valid base register. */ info->type = ADDRESS_CONST_INT; @@ -1018,7 +1077,7 @@ riscv_address_insns (rtx x, machine_mode mode, bool might_split_p) /* BLKmode is used for single unaligned loads and stores and should not count as a multiword mode. */ - if (mode != BLKmode && might_split_p) + if (!riscv_v_ext_vector_mode_p (mode) && mode != BLKmode && might_split_p) n += (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (addr.type == ADDRESS_LO_SUM) @@ -1077,6 +1136,12 @@ riscv_const_insns (rtx x) case LABEL_REF: return riscv_symbol_insns (riscv_classify_symbol (x)); + /* TODO: In RVV, we get CONST_POLY_INT by using csrr VLENB + instruction and several scalar shift or mult instructions, + it is so far unknown. We set it to 4 temporarily. */ + case CONST_POLY_INT: + return 4; + default: return 0; } @@ -1550,6 +1615,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value, x = riscv_split_integer (value, mode); else { + codes[0].value = trunc_int_for_mode (codes[0].value, mode); /* Apply each binary operation to X. */ x = GEN_INT (codes[0].value); @@ -1559,7 +1625,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value, x = riscv_emit_set (temp, x); else x = force_reg (mode, x); - + codes[i].value = trunc_int_for_mode (codes[i].value, mode); x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); } } @@ -1754,7 +1820,8 @@ riscv_immediate_operand_p (int code, HOST_WIDE_INT x) static int riscv_binary_cost (rtx x, int single_insns, int double_insns) { - if (GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2) + if (!riscv_v_ext_vector_mode_p (GET_MODE (x)) + && GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2) return COSTS_N_INSNS (double_insns); return COSTS_N_INSNS (single_insns); } @@ -1801,6 +1868,14 @@ static bool riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED, int *total, bool speed) { + /* TODO: We set RVV instruction cost as 1 by default. + Cost Model need to be well analyzed and supported in the future. */ + if (riscv_v_ext_vector_mode_p (mode)) + { + *total = COSTS_N_INSNS (1); + return true; + } + bool float_mode_p = FLOAT_MODE_P (mode); int cost; @@ -2438,6 +2513,12 @@ riscv_output_move (rtx dest, rtx src) return "fld\t%0,%1"; } } + if (dest_code == REG && GP_REG_P (REGNO (dest)) && src_code == CONST_POLY_INT) + { + /* We only want a single full vector register VLEN read after reload. */ + gcc_assert (known_eq (rtx_to_poly_int64 (src), BYTES_PER_RISCV_VECTOR)); + return "csrr\t%0,vlenb"; + } gcc_unreachable (); } @@ -2651,6 +2732,7 @@ riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1) continue; new_rhs = rhs + (increment ? 1 : -1); + new_rhs = trunc_int_for_mode (new_rhs, GET_MODE (*op0)); if (riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs) && (rhs < 0) == (new_rhs < 0)) { @@ -3730,11 +3812,23 @@ riscv_memmodel_needs_release_fence (enum memmodel model) 'z' Print x0 if OP is zero, otherwise print OP normally. 'i' Print i if the operand is not a register. 'S' Print shift-index of single-bit mask OP. - 'T' Print shift-index of inverted single-bit mask OP. */ + 'T' Print shift-index of inverted single-bit mask OP. + '~' Print w if TARGET_64BIT is true; otherwise not print anything. + + Note please keep this list and the list in riscv.md in sync. */ static void riscv_print_operand (FILE *file, rtx op, int letter) { + /* `~` does not take an operand so op will be null + Check for before accessing op. + */ + if (letter == '~') + { + if (TARGET_64BIT) + fputc('w', file); + return; + } machine_mode mode = GET_MODE (op); enum rtx_code code = GET_CODE (op); @@ -3810,6 +3904,13 @@ riscv_print_operand (FILE *file, rtx op, int letter) } } +/* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P */ +static bool +riscv_print_operand_punct_valid_p (unsigned char code) +{ + return (code == '~'); +} + /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ static void @@ -4110,7 +4211,7 @@ riscv_compute_frame_info (void) interrupt_save_prologue_temp = true; } - memset (frame, 0, sizeof (*frame)); + frame->reset(); if (!cfun->machine->naked_p) { @@ -4844,7 +4945,8 @@ static bool riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1, reg_class_t class2) { - return (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD + return (!riscv_v_ext_vector_mode_p (mode) + && GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD && (class1 == FP_REGS) != (class2 == FP_REGS)); } @@ -4866,6 +4968,25 @@ riscv_register_move_cost (machine_mode mode, static unsigned int riscv_hard_regno_nregs (unsigned int regno, machine_mode mode) { + if (riscv_v_ext_vector_mode_p (mode)) + { + /* Handle fractional LMUL, it only occupy part of vector register but + still need one vector register to hold. */ + if (maybe_lt (GET_MODE_SIZE (mode), UNITS_PER_V_REG)) + return 1; + + return exact_div (GET_MODE_SIZE (mode), UNITS_PER_V_REG).to_constant (); + } + + /* mode for VL or VTYPE are just a marker, not holding value, + so it always consume one register. */ + if (regno == VTYPE_REGNUM || regno == VL_REGNUM) + return 1; + + /* Assume every valid non-vector mode fits in one vector register. */ + if (V_REG_P (regno)) + return 1; + if (FP_REG_P (regno)) return (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG; @@ -4882,11 +5003,17 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (GP_REG_P (regno)) { + if (riscv_v_ext_vector_mode_p (mode)) + return false; + if (!GP_REG_P (regno + nregs - 1)) return false; } else if (FP_REG_P (regno)) { + if (riscv_v_ext_vector_mode_p (mode)) + return false; + if (!FP_REG_P (regno + nregs - 1)) return false; @@ -4901,6 +5028,19 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode) && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG)) return false; } + else if (V_REG_P (regno)) + { + if (!riscv_v_ext_vector_mode_p (mode)) + return false; + + /* 3.3.2. LMUL = 2,4,8, register numbers should be multiple of 2,4,8. + but for mask vector register, register numbers can be any number. */ + int lmul = 1; + if (known_gt (GET_MODE_SIZE (mode), UNITS_PER_V_REG)) + lmul = exact_div (GET_MODE_SIZE (mode), UNITS_PER_V_REG).to_constant (); + if (lmul != 1) + return ((regno % lmul) == 0); + } else return false; @@ -4937,6 +5077,15 @@ riscv_class_max_nregs (reg_class_t rclass, machine_mode mode) if (reg_class_subset_p (rclass, GR_REGS)) return riscv_hard_regno_nregs (GP_REG_FIRST, mode); + if (reg_class_subset_p (rclass, V_REGS)) + return riscv_hard_regno_nregs (V_REG_FIRST, mode); + + if (reg_class_subset_p (rclass, VL_REGS)) + return 1; + + if (reg_class_subset_p (rclass, VTYPE_REGS)) + return 1; + return 0; } @@ -5082,22 +5231,23 @@ riscv_init_machine_status (void) static poly_uint16 riscv_convert_vector_bits (void) { - /* The runtime invariant is only meaningful when vector is enabled. */ + /* The runtime invariant is only meaningful when TARGET_VECTOR is enabled. */ if (!TARGET_VECTOR) return 0; - if (TARGET_VECTOR_ELEN_64 || TARGET_VECTOR_ELEN_FP_64) + if (TARGET_MIN_VLEN > 32) { - /* When targetting Zve64* (ELEN = 64) extensions, we should use 64-bit - chunk size. Runtime invariant: The single indeterminate represent the + /* When targetting minimum VLEN > 32, we should use 64-bit chunk size. + Otherwise we can not include SEW = 64bits. + Runtime invariant: The single indeterminate represent the number of 64-bit chunks in a vector beyond minimum length of 64 bits. Thus the number of bytes in a vector is 8 + 8 * x1 which is - riscv_vector_chunks * 8 = poly_int (8, 8). */ + riscv_vector_chunks * 8 = poly_int (8, 8). */ riscv_bytes_per_vector_chunk = 8; } else { - /* When targetting Zve32* (ELEN = 32) extensions, we should use 32-bit + /* When targetting minimum VLEN = 32, we should use 32-bit chunk size. Runtime invariant: The single indeterminate represent the number of 32-bit chunks in a vector beyond minimum length of 32 bits. Thus the number of bytes in a vector is 4 + 4 * x1 which is @@ -5288,6 +5438,15 @@ riscv_conditional_register_usage (void) for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) call_used_regs[regno] = 1; } + + if (!TARGET_VECTOR) + { + for (int regno = V_REG_FIRST; regno <= V_REG_LAST; regno++) + fixed_regs[regno] = call_used_regs[regno] = 1; + + fixed_regs[VTYPE_REGNUM] = call_used_regs[VTYPE_REGNUM] = 1; + fixed_regs[VL_REGNUM] = call_used_regs[VL_REGNUM] = 1; + } } /* Return a register priority for hard reg REGNO. */ @@ -5898,6 +6057,8 @@ riscv_init_libfuncs (void) #define TARGET_PRINT_OPERAND riscv_print_operand #undef TARGET_PRINT_OPERAND_ADDRESS #define TARGET_PRINT_OPERAND_ADDRESS riscv_print_operand_address +#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P +#define TARGET_PRINT_OPERAND_PUNCT_VALID_P riscv_print_operand_punct_valid_p #undef TARGET_SETUP_INCOMING_VARARGS #define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 4b07c54..eb1284e 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -27,10 +27,6 @@ along with GCC; see the file COPYING3. If not see /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() riscv_cpu_cpp_builtins (pfile) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS riscv_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO riscv_d_register_target_info - #ifdef TARGET_BIG_ENDIAN_DEFAULT #define DEFAULT_ENDIAN_SPEC "b" #else @@ -50,11 +46,13 @@ along with GCC; see the file COPYING3. If not see extern const char *riscv_expand_arch (int argc, const char **argv); extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv); extern const char *riscv_default_mtune (int argc, const char **argv); +extern const char *riscv_multi_lib_check (int argc, const char **argv); # define EXTRA_SPEC_FUNCTIONS \ { "riscv_expand_arch", riscv_expand_arch }, \ { "riscv_expand_arch_from_cpu", riscv_expand_arch_from_cpu }, \ - { "riscv_default_mtune", riscv_default_mtune }, + { "riscv_default_mtune", riscv_default_mtune }, \ + { "riscv_multi_lib_check", riscv_multi_lib_check }, /* Support for a compile-time default CPU, et cetera. The rules are: --with-arch is ignored if -march or -mcpu is specified. @@ -122,8 +120,13 @@ ASM_MISA_SPEC #define DWARF_CIE_DATA_ALIGNMENT -4 /* The mapping from gcc register number to DWARF 2 CFA column number. */ -#define DWARF_FRAME_REGNUM(REGNO) \ - (GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM) +#define DWARF_FRAME_REGNUM(REGNO) \ + (VL_REG_P (REGNO) ? RISCV_DWARF_VL \ + : VTYPE_REG_P (REGNO) \ + ? RISCV_DWARF_VTYPE \ + : (GP_REG_P (REGNO) || FP_REG_P (REGNO) || V_REG_P (REGNO) \ + ? REGNO \ + : INVALID_REGNUM)) /* The DWARF 2 CFA column which tracks the return address. */ #define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM @@ -155,6 +158,8 @@ ASM_MISA_SPEC /* The `Q' extension is not yet supported. */ #define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4) +/* Size per vector register. For VLEN = 32, size = poly (4, 4). Otherwise, size = poly (8, 8). */ +#define UNITS_PER_V_REG (riscv_vector_chunks * riscv_bytes_per_vector_chunk) /* The largest type that can be passed in floating-point registers. */ #define UNITS_PER_FP_ARG \ @@ -289,9 +294,13 @@ ASM_MISA_SPEC - 32 floating point registers - 2 fake registers: - ARG_POINTER_REGNUM - - FRAME_POINTER_REGNUM */ + - FRAME_POINTER_REGNUM + - 1 vl register + - 1 vtype register + - 30 unused registers for future expansion + - 32 vector registers */ -#define FIRST_PSEUDO_REGISTER 66 +#define FIRST_PSEUDO_REGISTER 128 /* x0, sp, gp, and tp are fixed. */ @@ -303,7 +312,11 @@ ASM_MISA_SPEC 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Others. */ \ - 1, 1 \ + 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + /* Vector registers. */ \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ } /* a0-a7, t0-t6, fa0-fa7, and ft0-ft11 are volatile across calls. @@ -317,7 +330,11 @@ ASM_MISA_SPEC 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \ /* Others. */ \ - 1, 1 \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + /* Vector registers. */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \ } /* Select a register mode required for caller save of hard regno REGNO. @@ -337,6 +354,10 @@ ASM_MISA_SPEC #define FP_REG_LAST 63 #define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1) +#define V_REG_FIRST 96 +#define V_REG_LAST 127 +#define V_REG_NUM (V_REG_LAST - V_REG_FIRST + 1) + /* The DWARF 2 CFA column which tracks the return address from a signal handler context. This means that to maintain backwards compatibility, no hard register can be assigned this column if it @@ -347,6 +368,10 @@ ASM_MISA_SPEC ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM) #define FP_REG_P(REGNO) \ ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM) +#define V_REG_P(REGNO) \ + ((unsigned int) ((int) (REGNO) - V_REG_FIRST) < V_REG_NUM) +#define VL_REG_P(REGNO) ((REGNO) == VL_REGNUM) +#define VTYPE_REG_P(REGNO) ((REGNO) == VTYPE_REGNUM) /* True when REGNO is in SIBCALL_REGS set. */ #define SIBCALL_REG_P(REGNO) \ @@ -364,6 +389,10 @@ ASM_MISA_SPEC #define ARG_POINTER_REGNUM 64 #define FRAME_POINTER_REGNUM 65 +/* Define Dwarf for RVV. */ +#define RISCV_DWARF_VL (4096 + 0xc20) +#define RISCV_DWARF_VTYPE (4096 + 0xc21) + /* Register in which static-chain is passed to a function. */ #define STATIC_CHAIN_REGNUM (GP_TEMP_FIRST + 2) @@ -430,6 +459,11 @@ enum reg_class GR_REGS, /* integer registers */ FP_REGS, /* floating-point registers */ FRAME_REGS, /* arg pointer and frame pointer */ + VL_REGS, /* vl register */ + VTYPE_REGS, /* vtype register */ + VM_REGS, /* v0.t registers */ + VD_REGS, /* vector registers except v0.t */ + V_REGS, /* vector registers */ ALL_REGS, /* all registers */ LIM_REG_CLASSES /* max value + 1 */ }; @@ -450,6 +484,11 @@ enum reg_class "GR_REGS", \ "FP_REGS", \ "FRAME_REGS", \ + "VL_REGS", \ + "VTYPE_REGS", \ + "VM_REGS", \ + "VD_REGS", \ + "V_REGS", \ "ALL_REGS" \ } @@ -466,13 +505,18 @@ enum reg_class #define REG_CLASS_CONTENTS \ { \ - { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ - { 0xf003fcc0, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \ - { 0xffffffc0, 0x00000000, 0x00000000 }, /* JALR_REGS */ \ - { 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \ - { 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \ - { 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \ - { 0xffffffff, 0xffffffff, 0x00000003 } /* ALL_REGS */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ + { 0xf003fcc0, 0x00000000, 0x00000000, 0x00000000 }, /* SIBCALL_REGS */ \ + { 0xffffffc0, 0x00000000, 0x00000000, 0x00000000 }, /* JALR_REGS */ \ + { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 }, /* GR_REGS */ \ + { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FP_REGS */ \ + { 0x00000000, 0x00000000, 0x00000003, 0x00000000 }, /* FRAME_REGS */ \ + { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* VL_REGS */ \ + { 0x00000000, 0x00000000, 0x00000008, 0x00000000 }, /* VTYPE_REGS */ \ + { 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, /* V0_REGS */ \ + { 0x00000000, 0x00000000, 0x00000000, 0xfffffffe }, /* VNoV0_REGS */ \ + { 0x00000000, 0x00000000, 0x00000000, 0xffffffff }, /* V_REGS */ \ + { 0xffffffff, 0xffffffff, 0x00000003, 0x00000000 } /* ALL_REGS */ \ } /* A C expression whose value is a register class containing hard @@ -512,9 +556,16 @@ enum reg_class 60, 61, 62, 63, \ /* Call-saved FPRs. */ \ 40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \ + /* V24 ~ V31. */ \ + 120, 121, 122, 123, 124, 125, 126, 127, \ + /* V8 ~ V23. */ \ + 104, 105, 106, 107, 108, 109, 110, 111, \ + 112, 113, 114, 115, 116, 117, 118, 119, \ + /* V0 ~ V7. */ \ + 96, 97, 98, 99, 100, 101, 102, 103, \ /* None of the remaining classes have defined call-saved \ registers. */ \ - 64, 65 \ + 64, 65, 66, 67 \ } /* True if VALUE is a signed 12-bit number. */ @@ -535,7 +586,9 @@ enum reg_class /* If this is a single bit mask, then we can load it with bseti. Special handling of SImode 0x80000000 on RV64 is done in riscv_build_integer_1. */ #define SINGLE_BIT_MASK_OPERAND(VALUE) \ - (pow2p_hwi (VALUE)) + (pow2p_hwi (TARGET_64BIT \ + ? (VALUE) \ + : ((VALUE) & ((HOST_WIDE_INT_1U << 32)-1)))) /* Stack layout; function entry, exit and calling. */ @@ -781,7 +834,14 @@ typedef struct { "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \ "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \ "fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \ - "arg", "frame", } + "arg", "frame", "vl", "vtype", "N/A", "N/A", "N/A", "N/A", \ + "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \ + "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \ + "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \ + "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", \ + "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", \ + "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", \ + "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",} #define ADDITIONAL_REGISTER_NAMES \ { \ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index f4a5ff0..2bfab19 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -19,6 +19,21 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. + +;; Keep this list and the one above riscv_print_operand in sync. +;; The special asm out single letter directives following a '%' are: +;; h -- Print the high-part relocation associated with OP, after stripping +;; any outermost HIGH. +;; R -- Print the low-part relocation associated with OP. +;; C -- Print the integer branch condition for comparison OP. +;; A -- Print the atomic operation suffix for memory model OP. +;; F -- Print a FENCE if the memory model requires a release. +;; z -- Print x0 if OP is zero, otherwise print OP normally. +;; i -- Print i if the operand is not a register. +;; S -- Print shift-index of single-bit mask OP. +;; T -- Print shift-index of inverted single-bit mask OP. +;; ~ -- Print w if TARGET_64BIT is true; otherwise not print anything. + (define_c_enum "unspec" [ ;; Override return address for exception handling. UNSPEC_EH_RETURN @@ -103,10 +118,13 @@ (NORMAL_RETURN 0) (SIBCALL_RETURN 1) (EXCEPTION_RETURN 2) + (VL_REGNUM 66) + (VTYPE_REGNUM 67) ]) (include "predicates.md") (include "constraints.md") +(include "iterators.md") ;; .................... ;; @@ -130,7 +148,7 @@ ;; scheduling type to be "multi" instead. (define_attr "move_type" "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove, - const,logical,arith,andi,shift_shift" + const,logical,arith,andi,shift_shift,rdvlenb" (const_string "unknown")) ;; Main data type used by the insn @@ -148,6 +166,35 @@ (const_string "yes")] (const_string "no"))) +;; ISA attributes. +(define_attr "ext" "base,f,d,vector" + (const_string "base")) + +;; True if the extension is enabled. +(define_attr "ext_enabled" "no,yes" + (cond [(eq_attr "ext" "base") + (const_string "yes") + + (and (eq_attr "ext" "f") + (match_test "TARGET_HARD_FLOAT")) + (const_string "yes") + + (and (eq_attr "ext" "d") + (match_test "TARGET_DOUBLE_FLOAT")) + (const_string "yes") + + (and (eq_attr "ext" "vector") + (match_test "TARGET_VECTOR")) + (const_string "yes") + ] + (const_string "no"))) + +;; Attribute to control enable or disable instructions. +(define_attr "enabled" "no,yes" + (cond [(eq_attr "ext_enabled" "no") + (const_string "no")] + (const_string "yes"))) + ;; Classification of each insn. ;; branch conditional branch ;; jump unconditional jump @@ -179,10 +226,108 @@ ;; nop no operation ;; ghost an instruction that produces no real code ;; bitmanip bit manipulation instructions +;; Classification of RVV instructions which will be added to each RVV .md pattern and used by scheduler. +;; rdvlenb vector byte length vlenb csrr read +;; rdvl vector length vl csrr read +;; 7. Vector Loads and Stores +;; vlde vector unit-stride load instructions +;; vste vector unit-stride store instructions +;; vldm vector unit-stride mask load instructions +;; vstm vector unit-stride mask store instructions +;; vlds vector strided load instructions +;; vsts vector strided store instructions +;; vldux vector unordered indexed load instructions +;; vldox vector ordered indexed load instructions +;; vstux vector unordered indexed store instructions +;; vstox vector ordered indexed store instructions +;; vldff vector unit-stride fault-only-first load instructions +;; vldr vector whole register load instructions +;; vstr vector whole register store instructions +;; 11. Vector integer arithmetic instructions +;; vialu vector single-width integer add and subtract and logical nstructions +;; viwalu vector widening integer add/subtract +;; vext vector integer extension +;; vicalu vector arithmetic with carry or borrow instructions +;; vshift vector single-width bit shift instructions +;; vnshift vector narrowing integer shift instructions +;; vicmp vector integer comparison/min/max instructions +;; vimul vector single-width integer multiply instructions +;; vidiv vector single-width integer divide instructions +;; viwmul vector widening integer multiply instructions +;; vimuladd vector single-width integer multiply-add instructions +;; viwmuladd vector widening integer multiply-add instructions +;; vimerge vector integer merge instructions +;; vimov vector integer move vector instructions +;; 12. Vector fixed-point arithmetic instructions +;; vsalu vector single-width saturating add and subtract and logical instructions +;; vaalu vector single-width averaging add and subtract and logical instructions +;; vsmul vector single-width fractional multiply with rounding and saturation instructions +;; vsshift vector single-width scaling shift instructions +;; vnclip vector narrowing fixed-point clip instructions +;; 13. Vector floating-point instructions +;; vfalu vector single-width floating-point add/subtract instructions +;; vfwalu vector widening floating-point add/subtract instructions +;; vfmul vector single-width floating-point multiply instructions +;; vfdiv vector single-width floating-point divide instructions +;; vfwmul vector widening floating-point multiply instructions +;; vfmuladd vector single-width floating-point multiply-add instructions +;; vfwmuladd vector widening floating-point multiply-add instructions +;; vfsqrt vector floating-point square-root instructions +;; vfrecp vector floating-point reciprocal square-root instructions +;; vfcmp vector floating-point comparison/min/max instructions +;; vfsgnj vector floating-point sign-injection instructions +;; vfclass vector floating-point classify instruction +;; vfmerge vector floating-point merge instruction +;; vfmov vector floating-point move instruction +;; vfcvtitof vector single-width integer to floating-point instruction +;; vfcvtftoi vector single-width floating-point to integer instruction +;; vfwcvtitof vector widening integer to floating-point instruction +;; vfwcvtftoi vector widening floating-point to integer instruction +;; vfwcvtftof vector widening floating-point to floating-point instruction +;; vfncvtitof vector narrowing integer to floating-point instruction +;; vfncvtftoi vector narrowing floating-point to integer instruction +;; vfncvtftof vector narrowing floating-point to floating-point instruction +;; 14. Vector reduction operations +;; vired vector single-width integer reduction instructions +;; viwred vector widening integer reduction instructions +;; vfred vector single-width floating-point un-ordered reduction instruction +;; vfredo vector single-width floating-point ordered reduction instruction +;; vfwred vector widening floating-point un-ordered reduction instruction +;; vfwredo vector widening floating-point ordered reduction instruction +;; 15. Vector mask instructions +;; vmalu vector mask-register logical instructions +;; vmpop vector mask population count +;; vmffs vector find-first-set mask bit +;; vmsfs vector set mask bit +;; vmiota vector iota +;; vmidx vector element index instruction +;; 16. Vector permutation instructions +;; vimovvx integer scalar move instructions +;; vimovxv integer scalar move instructions +;; vfmovvf floating-point scalar move instructions +;; vfmovfv floating-point scalar move instructions +;; vislide vector slide instructions +;; vislide1 vector slide instructions +;; vfslide1 vector slide instructions +;; vgather vector register gather instructions +;; vcompress vector compress instruction +;; vmov whole vector register move (define_attr "type" "unknown,branch,jump,call,load,fpload,store,fpstore, mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, - fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate" + fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate, + rdvlenb,rdvl,vlde,vste,vldm,vstm,vlds,vsts, + vldux,vldox,vstux,vstox,vldff,vldr,vstr, + vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp, + vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov, + vsalu,vaalu,vsmul,vsshift,vnclip, + vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp, + vfcmp,vfsgnj,vfclass,vfmerge,vfmov, + vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi, + vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof, + vired,viwred,vfred,vfredo,vfwred,vfwredo, + vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv, + vislide,vislide1,vfslide1,vgather,vcompress,vmov" (cond [(eq_attr "got" "load") (const_string "load") ;; If a doubleword move uses these expensive instructions, @@ -210,7 +355,8 @@ (eq_attr "dword_mode" "yes")) (const_string "multi") (eq_attr "move_type" "move") (const_string "move") - (eq_attr "move_type" "const") (const_string "const")] + (eq_attr "move_type" "const") (const_string "const") + (eq_attr "move_type" "rdvlenb") (const_string "rdvlenb")] (const_string "unknown"))) ;; Length of instruction in bytes. @@ -269,175 +415,6 @@ (define_asm_attributes [(set_attr "type" "multi")]) -;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated -;; from the same template. -(define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) - -;; This mode iterator allows :P to be used for patterns that operate on -;; pointer-sized quantities. Exactly one of the two alternatives will match. -(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) - -;; Likewise, but for XLEN-sized quantities. -(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) - -;; Branches operate on XLEN-sized quantities, but for RV64 we accept -;; QImode values so we can force zero-extension. -(define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")]) - -;; 32-bit moves for which we provide move patterns. -(define_mode_iterator MOVE32 [SI]) - -;; 64-bit modes for which we provide move patterns. -(define_mode_iterator MOVE64 [DI DF]) - -;; Iterator for sub-32-bit integer modes. -(define_mode_iterator SHORT [QI HI]) - -;; Iterator for HImode constant generation. -(define_mode_iterator HISI [HI SI]) - -;; Iterator for QImode extension patterns. -(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) - -;; Iterator for hardware integer modes narrower than XLEN. -(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) - -;; Iterator for hardware-supported integer modes. -(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) - -;; Iterator for hardware-supported floating-point modes. -(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") - (DF "TARGET_DOUBLE_FLOAT") - (HF "TARGET_ZFH")]) - -;; Iterator for floating-point modes that can be loaded into X registers. -(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) - -;; This attribute gives the length suffix for a sign- or zero-extension -;; instruction. -(define_mode_attr size [(QI "b") (HI "h")]) - -;; Mode attributes for loads. -(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")]) - -;; Instruction names for integer loads that aren't explicitly sign or zero -;; extended. See riscv_output_move and LOAD_EXTEND_OP. -(define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")]) - -;; Mode attribute for FP loads into integer registers. -(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) - -;; Instruction names for stores. -(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")]) - -;; Instruction names for FP stores from integer registers. -(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) - -;; This attribute gives the best constraint to use for registers of -;; a given mode. -(define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) - -;; This attribute gives the format suffix for floating-point operations. -(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")]) - -;; This attribute gives the integer suffix for floating-point conversions. -(define_mode_attr ifmt [(SI "w") (DI "l")]) - -;; This attribute gives the format suffix for atomic memory operations. -(define_mode_attr amo [(SI "w") (DI "d")]) - -;; This attribute gives the upper-case mode name for one unit of a -;; floating-point mode. -(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")]) - -;; This attribute gives the integer mode that has half the size of -;; the controlling mode. -(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) - -;; Iterator and attributes for floating-point rounding instructions. -(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND]) -(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")]) -(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")]) - -;; Iterator and attributes for quiet comparisons. -(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) -(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) -(define_int_attr QUIET_PATTERN [(UNSPEC_FLT_QUIET "LT") (UNSPEC_FLE_QUIET "LE")]) - -;; This code iterator allows signed and unsigned widening multiplications -;; to use the same template. -(define_code_iterator any_extend [sign_extend zero_extend]) - -;; This code iterator allows the two right shift instructions to be -;; generated from the same template. -(define_code_iterator any_shiftrt [ashiftrt lshiftrt]) - -;; This code iterator allows the three shift instructions to be generated -;; from the same template. -(define_code_iterator any_shift [ashift ashiftrt lshiftrt]) - -;; This code iterator allows the three bitwise instructions to be generated -;; from the same template. -(define_code_iterator any_bitwise [and ior xor]) - -;; This code iterator allows unsigned and signed division to be generated -;; from the same template. -(define_code_iterator any_div [div udiv mod umod]) - -;; This code iterator allows unsigned and signed modulus to be generated -;; from the same template. -(define_code_iterator any_mod [mod umod]) - -;; These code iterators allow the signed and unsigned scc operations to use -;; the same template. -(define_code_iterator any_gt [gt gtu]) -(define_code_iterator any_ge [ge geu]) -(define_code_iterator any_lt [lt ltu]) -(define_code_iterator any_le [le leu]) - -;; <u> expands to an empty string when doing a signed operation and -;; "u" when doing an unsigned operation. -(define_code_attr u [(sign_extend "") (zero_extend "u") - (gt "") (gtu "u") - (ge "") (geu "u") - (lt "") (ltu "u") - (le "") (leu "u")]) - -;; <su> is like <u>, but the signed form expands to "s" rather than "". -(define_code_attr su [(sign_extend "s") (zero_extend "u")]) - -;; <optab> expands to the name of the optab for a particular code. -(define_code_attr optab [(ashift "ashl") - (ashiftrt "ashr") - (lshiftrt "lshr") - (div "div") - (mod "mod") - (udiv "udiv") - (umod "umod") - (ge "ge") - (le "le") - (gt "gt") - (lt "lt") - (ior "ior") - (xor "xor") - (and "and") - (plus "add") - (minus "sub")]) - -;; <insn> expands to the name of the insn that implements a particular code. -(define_code_attr insn [(ashift "sll") - (ashiftrt "sra") - (lshiftrt "srl") - (div "div") - (mod "rem") - (udiv "divu") - (umod "remu") - (ior "or") - (xor "xor") - (and "and") - (plus "add") - (minus "sub")]) - ;; Ghost instructions produce no real code and introduce no hazards. ;; They exist purely to express an effect on dataflow. (define_insn_reservation "ghost" 0 @@ -466,7 +443,7 @@ (plus:SI (match_operand:SI 1 "register_operand" " r,r") (match_operand:SI 2 "arith_operand" " r,I")))] "" - { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; } + "add%i2%~\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -606,7 +583,7 @@ (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ") (match_operand:SI 2 "register_operand" " r")))] "" - { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; } + "sub%~\t%0,%z1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -722,7 +699,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "register_operand" " r")))] "" - { return TARGET_64BIT ? "negw\t%0,%1" : "neg\t%0,%1"; } + "neg%~\t%0,%1" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -767,7 +744,7 @@ (mult:SI (match_operand:SI 1 "register_operand" " r") (match_operand:SI 2 "register_operand" " r")))] "TARGET_MUL" - { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; } + "mul%~\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) @@ -1037,7 +1014,7 @@ (any_div:SI (match_operand:SI 1 "register_operand" " r") (match_operand:SI 2 "register_operand" " r")))] "TARGET_DIV" - { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; } + "<insn>%i2%~\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI")]) @@ -1686,24 +1663,26 @@ }) (define_insn "*movdi_32bit" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m") - (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r") + (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))] "!TARGET_64BIT && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" { return riscv_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") - (set_attr "mode" "DI")]) + [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb") + (set_attr "mode" "DI") + (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")]) (define_insn "*movdi_64bit" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m") - (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r") + (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))] "TARGET_64BIT && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" { return riscv_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") - (set_attr "mode" "DI")]) + [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb") + (set_attr "mode" "DI") + (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")]) ;; 32-bit Integer moves @@ -1717,13 +1696,14 @@ }) (define_insn "*movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m") - (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m,r") + (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,vp"))] "(register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode))" { return riscv_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore") - (set_attr "mode" "SI")]) + [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore,rdvlenb") + (set_attr "mode" "SI") + (set_attr "ext" "base,base,base,base,f,f,f,f,vector")]) ;; 16-bit Integer moves @@ -1742,13 +1722,14 @@ }) (define_insn "*movhi_internal" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r") - (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r") + (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f,vp"))] "(register_operand (operands[0], HImode) || reg_or_0_operand (operands[1], HImode))" { return riscv_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtc,mfc") - (set_attr "mode" "HI")]) + [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb") + (set_attr "mode" "HI") + (set_attr "ext" "base,base,base,base,f,f,vector")]) ;; HImode constant generation; see riscv_move_integer for details. ;; si+si->hi without truncation is legal because of @@ -1759,7 +1740,7 @@ (plus:HI (match_operand:HISI 1 "register_operand" " r,r") (match_operand:HISI 2 "arith_operand" " r,I")))] "" - { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; } + "add%i2%~\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "HI")]) @@ -1784,13 +1765,14 @@ }) (define_insn "*movqi_internal" - [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r") - (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r") + (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f,vp"))] "(register_operand (operands[0], QImode) || reg_or_0_operand (operands[1], QImode))" { return riscv_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtc,mfc") - (set_attr "mode" "QI")]) + [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb") + (set_attr "mode" "QI") + (set_attr "ext" "base,base,base,base,f,f,vector")]) ;; 32-bit floating point moves @@ -1941,7 +1923,7 @@ operands[2] = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (SImode) - 1)); - return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; + return "<insn>%i2%~\t%0,%1,%2"; } [(set_attr "type" "shift") (set_attr "mode" "SI")]) diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md index 86b41e6b..7deb290 100644 --- a/gcc/config/riscv/sync.md +++ b/gcc/config/riscv/sync.md @@ -27,10 +27,6 @@ UNSPEC_MEMORY_BARRIER ]) -(define_code_iterator any_atomic [plus ior xor and]) -(define_code_attr atomic_optab - [(plus "add") (ior "or") (xor "xor") (and "and")]) - ;; Memory barriers. (define_expand "mem_thread_fence" diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index 12afa86..6dfb0db 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -51,9 +51,6 @@ #include "tree-ssa-propagate.h" #include "builtins.h" #include "tree-vector-builder.h" -#if TARGET_XCOFF -#include "xcoffout.h" /* get declarations of xcoff_*_section_name */ -#endif #include "ppc-auxv.h" #include "rs6000-internal.h" @@ -1085,7 +1082,12 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi, unsigned nvec = (fncode == RS6000_BIF_DISASSEMBLE_ACC) ? 4 : 2; tree dst_ptr = gimple_call_arg (stmt, 0); tree src_ptr = gimple_call_arg (stmt, 1); - tree src_type = TREE_TYPE (src_ptr); + tree src_type = (fncode == RS6000_BIF_DISASSEMBLE_ACC) + ? build_pointer_type (vector_quad_type_node) + : build_pointer_type (vector_pair_type_node); + if (TREE_TYPE (src_ptr) != src_type) + src_ptr = build1 (NOP_EXPR, src_type, src_ptr); + tree src = create_tmp_reg_or_ssa_name (TREE_TYPE (src_type)); gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq); @@ -1096,7 +1098,7 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi, || (fncode == RS6000_BIF_DISASSEMBLE_PAIR_V && TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_pair_type_node)) { - tree dst = build_simple_mem_ref (build1 (VIEW_CONVERT_EXPR, + tree dst = build_simple_mem_ref (build1 (NOP_EXPR, src_type, dst_ptr)); gimplify_assign (dst, src, &new_seq); pop_gimplify_context (NULL); @@ -1120,7 +1122,7 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi, = rs6000_builtin_decls[rs6000_builtin_info[fncode].assoc_bif]; tree dst_type = build_pointer_type_for_mode (unsigned_V16QI_type_node, ptr_mode, true); - tree dst_base = build1 (VIEW_CONVERT_EXPR, dst_type, dst_ptr); + tree dst_base = build1 (NOP_EXPR, dst_type, dst_ptr); for (unsigned i = 0; i < nvec; i++) { unsigned index = WORDS_BIG_ENDIAN ? i : nvec - 1 - i; @@ -1146,7 +1148,7 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi, tree ptr = gimple_call_arg (stmt, 1); tree lhs = gimple_call_lhs (stmt); if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node) - ptr = build1 (VIEW_CONVERT_EXPR, + ptr = build1 (NOP_EXPR, build_pointer_type (vector_pair_type_node), ptr); tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset)); @@ -1163,7 +1165,7 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi, tree offset = gimple_call_arg (stmt, 1); tree ptr = gimple_call_arg (stmt, 2); if (TREE_TYPE (TREE_TYPE (ptr)) != vector_pair_type_node) - ptr = build1 (VIEW_CONVERT_EXPR, + ptr = build1 (NOP_EXPR, build_pointer_type (vector_pair_type_node), ptr); tree mem = build_simple_mem_ref (build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset)); diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index 551968b..ac3cb7e 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -61,20 +61,12 @@ #include "tree-ssa-propagate.h" #include "builtins.h" #include "tree-vector-builder.h" -#if TARGET_XCOFF -#include "xcoffout.h" /* get declarations of xcoff_*_section_name */ -#endif #include "ppc-auxv.h" #include "targhooks.h" #include "opts.h" #include "rs6000-internal.h" -#if TARGET_MACHO -#include "gstab.h" /* for N_SLINE */ -#include "dbxout.h" /* dbxout_ */ -#endif - #ifndef TARGET_PROFILE_KERNEL #define TARGET_PROFILE_KERNEL 0 #endif diff --git a/gcc/config/rs6000/rs6000-d.cc b/gcc/config/rs6000/rs6000-d.cc index 74e78cf..7b9ca5a 100644 --- a/gcc/config/rs6000/rs6000-d.cc +++ b/gcc/config/rs6000/rs6000-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/rs6000/rs6000-d.h b/gcc/config/rs6000/rs6000-d.h new file mode 100644 index 0000000..c805b30 --- /dev/null +++ b/gcc/config/rs6000/rs6000-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the PowerPC architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Declare functions in rs6000-d.cc */ +extern void rs6000_d_target_versions (void); +extern void rs6000_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS rs6000_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO rs6000_d_register_target_info diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index 59fe1c8..ddd849e 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -47,10 +47,6 @@ #include "diagnostic-core.h" #include "alias.h" #include "rs6000-internal.h" -#if TARGET_MACHO -#include "gstab.h" /* for N_SLINE */ -#include "dbxout.h" /* dbxout_ */ -#endif static int rs6000_ra_ever_killed (void); static void is_altivec_return_reg (rtx, void *); @@ -5144,10 +5140,6 @@ macho_branch_islands (void) } strcpy (tmp_buf, "\n"); strcat (tmp_buf, label); -#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) - if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) - dbxout_stabd (N_SLINE, bi->line_number); -#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ if (flag_pic) { strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); @@ -5181,10 +5173,6 @@ macho_branch_islands (void) strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr"); } output_asm_insn (tmp_buf, 0); -#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) - if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) - dbxout_stabd (N_SLINE, bi->line_number); -#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ branch_islands->pop (); } } diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index b3c16e7..d0d8932 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -291,7 +291,7 @@ extern int rs6000_trampoline_size (void); extern alias_set_type get_TOC_alias_set (void); extern void rs6000_emit_prologue (void); extern void rs6000_emit_load_toc_table (int); -extern unsigned int rs6000_dbx_register_number (unsigned int, unsigned int); +extern unsigned int rs6000_debugger_regno (unsigned int, unsigned int); extern void rs6000_emit_epilogue (enum epilogue_type); extern void rs6000_expand_split_stack_prologue (void); extern void rs6000_split_stack_space_check (rtx, rtx); @@ -323,10 +323,6 @@ extern void rs6000_activate_target_options (tree new_tree); extern void rs6000_target_modify_macros (bool, HOST_WIDE_INT); extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT); -/* Declare functions in rs6000-d.cc */ -extern void rs6000_d_target_versions (void); -extern void rs6000_d_register_target_info (void); - #ifdef NO_DOLLAR_IN_LABEL const char * rs6000_xcoff_strip_dollar (const char *); #endif diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index df491be..8b4edd2 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -75,9 +75,6 @@ #include "ipa-prop.h" #include "ipa-fnsummary.h" #include "except.h" -#if TARGET_XCOFF -#include "xcoffout.h" /* get declarations of xcoff_*_section_name */ -#endif #include "case-cfn-macros.h" #include "ppc-auxv.h" #include "rs6000-internal.h" @@ -3824,12 +3821,6 @@ rs6000_option_override_internal (bool global_init_p) if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) rs6000_print_isa_options (stderr, 0, "before defaults", rs6000_isa_flags); -#ifdef XCOFF_DEBUGGING_INFO - /* For AIX default to 64-bit DWARF. */ - if (!OPTION_SET_P (dwarf_offset_size)) - dwarf_offset_size = POINTER_SIZE_UNITS; -#endif - /* Handle explicit -mno-{altivec,vsx,power8-vector,power9-vector} and turn off all of the options that depend on those flags. */ ignore_masks = rs6000_disable_incompatible_switches (); @@ -20949,9 +20940,14 @@ rs6000_elf_file_end (void) #if TARGET_XCOFF -#ifndef HAVE_XCOFF_DWARF_EXTRAS -#define HAVE_XCOFF_DWARF_EXTRAS 0 -#endif +/* Names of bss and data sections. These should be unique names for each + compilation unit. */ + +char *xcoff_bss_section_name; +char *xcoff_private_data_section_name; +char *xcoff_private_rodata_section_name; +char *xcoff_tls_data_section_name; +char *xcoff_read_only_section_name; static enum unwind_info_type rs6000_xcoff_debug_unwind_info (void) @@ -21466,9 +21462,7 @@ rs6000_xcoff_declare_function_name (FILE *file, const char *name, tree decl) &data, true); if (!DECL_IGNORED_P (decl)) { - if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) - xcoffout_declare_function (file, decl, buffer); - else if (dwarf_debuginfo_p ()) + if (dwarf_debuginfo_p ()) { name = (*targetm.strip_name_encoding) (name); fprintf (file, "\t.function .%s,.%s,2,0\n", name, name); @@ -23643,7 +23637,7 @@ rs6000_init_dwarf_reg_sizes_extra (tree address) 2 -- DWARF .eh_frame section */ unsigned int -rs6000_dbx_register_number (unsigned int regno, unsigned int format) +rs6000_debugger_regno (unsigned int regno, unsigned int format) { /* On some platforms, we use the standard DWARF register numbering for .debug_info and .debug_frame. */ @@ -24861,6 +24855,7 @@ rs6000_get_function_versions_dispatcher (void *decl) /* Right now, the dispatching is done via ifunc. */ dispatch_decl = make_dispatcher_decl (default_node->decl); + TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn); dispatcher_node = cgraph_node::get_create (dispatch_decl); gcc_assert (dispatcher_node != NULL); @@ -28188,28 +28183,6 @@ rs6000_invalid_conversion (const_tree fromtype, const_tree totype) if (tomode == OOmode) return N_("invalid conversion to type %<__vector_pair%>"); } - else if (POINTER_TYPE_P (fromtype) && POINTER_TYPE_P (totype)) - { - /* We really care about the modes of the base types. */ - frommode = TYPE_MODE (TREE_TYPE (fromtype)); - tomode = TYPE_MODE (TREE_TYPE (totype)); - - /* Do not allow conversions to/from XOmode and OOmode pointer - types, except to/from void pointers. */ - if (frommode != tomode - && frommode != VOIDmode - && tomode != VOIDmode) - { - if (frommode == XOmode) - return N_("invalid conversion from type %<__vector_quad *%>"); - if (tomode == XOmode) - return N_("invalid conversion to type %<__vector_quad *%>"); - if (frommode == OOmode) - return N_("invalid conversion from type %<__vector_pair *%>"); - if (tomode == OOmode) - return N_("invalid conversion to type %<__vector_pair *%>"); - } - } /* Conversion allowed. */ return NULL; diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index ad9bf0f..eb7b215 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -606,10 +606,6 @@ extern unsigned char rs6000_recip_bits[]; #define TARGET_CPU_CPP_BUILTINS() \ rs6000_cpu_cpp_builtins (pfile) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS rs6000_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO rs6000_d_register_target_info - /* This is used by rs6000_cpu_cpp_builtins to indicate the byte order we're compiling for. Some configurations may need to override it. */ #define RS6000_CPU_CPP_ENDIAN_BUILTINS() \ @@ -795,7 +791,7 @@ enum data_align { align_abi, align_opt, align_both }; #define FIRST_PSEUDO_REGISTER 111 /* Use standard DWARF numbering for DWARF debugging information. */ -#define DBX_REGISTER_NUMBER(REGNO) rs6000_dbx_register_number ((REGNO), 0) +#define DEBUGGER_REGNO(REGNO) rs6000_debugger_regno ((REGNO), 0) /* Use gcc hard register numbering for eh_frame. */ #define DWARF_FRAME_REGNUM(REGNO) (REGNO) @@ -804,7 +800,7 @@ enum data_align { align_abi, align_opt, align_both }; collected using DWARF_FRAME_REGNUM to those that should be output in .debug_frame and .eh_frame. */ #define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) \ - rs6000_dbx_register_number ((REGNO), (FOR_EH) ? 2 : 1) + rs6000_debugger_regno ((REGNO), (FOR_EH) ? 2 : 1) /* 1 for registers that have pervasive standard uses and are not available for the register allocator. diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 7e2519d..c8b7eb6 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -504,9 +504,6 @@ extern int fixuplabelno; #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -/* Historically we have also supported stabs debugging. */ -#define DBX_DEBUGGING_INFO 1 - #define TARGET_ENCODE_SECTION_INFO rs6000_elf_encode_section_info #define TARGET_IN_SMALL_DATA_P rs6000_elf_in_small_data_p @@ -515,11 +512,6 @@ extern int fixuplabelno; #define RS6000_OUTPUT_BASENAME(FILE, NAME) \ assemble_name (FILE, NAME) -/* We have to output the stabs for the function name *first*, before - outputting its label. */ - -#define DBX_FUNCTION_FIRST - /* This is the end of what might become sysv4dbx.h. */ #define TARGET_OS_SYSV_CPP_BUILTINS() \ diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h index cd0f99c..bafc57d 100644 --- a/gcc/config/rs6000/xcoff.h +++ b/gcc/config/rs6000/xcoff.h @@ -21,9 +21,6 @@ #define TARGET_OBJECT_FORMAT OBJECT_XCOFF -/* The RS/6000 uses the XCOFF format. */ -#define XCOFF_DEBUGGING_INFO 1 - /* Define if the object format being used is COFF or a superset. */ #define OBJECT_FORMAT_COFF diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index ce9c2ff..77f8403 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -623,7 +623,6 @@ typedef unsigned int CUMULATIVE_ARGS; #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG -#define DBX_DEBUGGING_INFO 1 #define DWARF2_DEBUGGING_INFO 1 #define INCOMING_FRAME_SP_OFFSET 4 diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 33194d3..430cf6e 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -594,3 +594,15 @@ (define_predicate "addv_const_operand" (and (match_code "const_int") (match_test "INTVAL (op) >= -32768 && INTVAL (op) <= 32767"))) + +; Match (subreg (reg ...)) operands. +; Used for movstrict destination operands +; When replacing pseudos with hard regs reload strips away the +; subregs. Accept also plain registers then to prevent the insn from +; becoming unrecognizable. +(define_predicate "subreg_register_operand" + (ior (and (match_code "subreg") + (match_test "register_operand (SUBREG_REG (op), GET_MODE (SUBREG_REG (op)))")) + (and (match_code "reg") + (match_test "reload_completed || reload_in_progress") + (match_test "register_operand (op, GET_MODE (op))")))) diff --git a/gcc/config/s390/s390-d.cc b/gcc/config/s390/s390-d.cc index 8e63185..0dd4b5c 100644 --- a/gcc/config/s390/s390-d.cc +++ b/gcc/config/s390/s390-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/s390/s390-d.h b/gcc/config/s390/s390-d.h new file mode 100644 index 0000000..703031b --- /dev/null +++ b/gcc/config/s390/s390-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the IBM S/390 and zSeries architectures. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* s390-d.cc routines */ +extern void s390_d_target_versions (void); +extern void s390_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS s390_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO s390_d_register_target_info diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index fd4acaa..78117c3 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -50,6 +50,7 @@ extern void s390_set_has_landing_pad_p (bool); extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int); extern int s390_class_max_nregs (enum reg_class, machine_mode); extern bool s390_return_addr_from_memory(void); +extern rtx s390_gen_lowpart_subreg (machine_mode, rtx); extern bool s390_fma_allowed_p (machine_mode); #if S390_USE_TARGET_ATTRIBUTE extern tree s390_valid_target_attribute_tree (tree args, @@ -174,10 +175,6 @@ extern void s390_register_target_pragmas (void); /* Routines for s390-c.cc */ extern bool s390_const_operand_ok (tree, int, int, tree); -/* s390-d.cc routines */ -extern void s390_d_target_versions (void); -extern void s390_d_register_target_info (void); - /* Pass management. */ namespace gcc { class context; } class rtl_opt_pass; diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index 5aaf76a..3ae586c 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -430,6 +430,14 @@ struct s390_address bytes on a z10 (or higher) CPU. */ #define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048) +static int +s390_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED, + addr_space_t as ATTRIBUTE_UNUSED, + bool speed ATTRIBUTE_UNUSED); + +static unsigned int +s390_hard_regno_nregs (unsigned int regno, machine_mode mode); + /* Masks per jump target register indicating which thunk need to be generated. */ static GTY(()) int indirect_branch_prez10thunk_mask = 0; @@ -458,6 +466,31 @@ s390_return_addr_from_memory () return cfun_gpr_save_slot(RETURN_REGNUM) == SAVE_SLOT_STACK; } +/* Generate a SUBREG for the MODE lowpart of EXPR. + + In contrast to gen_lowpart it will always return a SUBREG + expression. This is useful to generate STRICT_LOW_PART + expressions. */ +rtx +s390_gen_lowpart_subreg (machine_mode mode, rtx expr) +{ + rtx lowpart = gen_lowpart (mode, expr); + + /* There might be no SUBREG in case it could be applied to the hard + REG rtx or it could be folded with a paradoxical subreg. Bring + it back. */ + if (!SUBREG_P (lowpart)) + { + machine_mode reg_mode = TARGET_ZARCH ? DImode : SImode; + gcc_assert (REG_P (lowpart)); + lowpart = gen_lowpart_SUBREG (mode, + gen_rtx_REG (reg_mode, + REGNO (lowpart))); + } + + return lowpart; +} + /* Return nonzero if it's OK to use fused multiply-add for MODE. */ bool s390_fma_allowed_p (machine_mode mode) @@ -3614,49 +3647,97 @@ s390_rtx_costs (rtx x, machine_mode mode, int outer_code, case MEM: *total = 0; return true; + case SET: { + rtx dest = SET_DEST (x); + rtx src = SET_SRC (x); - case SET: - { - /* Without this a conditional move instruction would be - accounted as 3 * COSTS_N_INSNS (set, if_then_else, - comparison operator). That's a bit pessimistic. */ + switch (GET_CODE (src)) + { + case IF_THEN_ELSE: { + /* Without this a conditional move instruction would be + accounted as 3 * COSTS_N_INSNS (set, if_then_else, + comparison operator). That's a bit pessimistic. */ - if (!TARGET_Z196 || GET_CODE (SET_SRC (x)) != IF_THEN_ELSE) - return false; + if (!TARGET_Z196) + return false; + + rtx cond = XEXP (src, 0); + if (!CC_REG_P (XEXP (cond, 0)) || !CONST_INT_P (XEXP (cond, 1))) + return false; - rtx cond = XEXP (SET_SRC (x), 0); + /* It is going to be a load/store on condition. Make it + slightly more expensive than a normal load. */ + *total = COSTS_N_INSNS (1) + 2; - if (!CC_REG_P (XEXP (cond, 0)) || !CONST_INT_P (XEXP (cond, 1))) - return false; + rtx dst = SET_DEST (src); + rtx then = XEXP (src, 1); + rtx els = XEXP (src, 2); - /* It is going to be a load/store on condition. Make it - slightly more expensive than a normal load. */ - *total = COSTS_N_INSNS (1) + 2; - - rtx dst = SET_DEST (x); - rtx then = XEXP (SET_SRC (x), 1); - rtx els = XEXP (SET_SRC (x), 2); - - /* It is a real IF-THEN-ELSE. An additional move will be - needed to implement that. */ - if (!TARGET_Z15 - && reload_completed - && !rtx_equal_p (dst, then) - && !rtx_equal_p (dst, els)) - *total += COSTS_N_INSNS (1) / 2; - - /* A minor penalty for constants we cannot directly handle. */ - if ((CONST_INT_P (then) || CONST_INT_P (els)) - && (!TARGET_Z13 || MEM_P (dst) - || (CONST_INT_P (then) && !satisfies_constraint_K (then)) - || (CONST_INT_P (els) && !satisfies_constraint_K (els)))) - *total += COSTS_N_INSNS (1) / 2; - - /* A store on condition can only handle register src operands. */ - if (MEM_P (dst) && (!REG_P (then) || !REG_P (els))) - *total += COSTS_N_INSNS (1) / 2; + /* It is a real IF-THEN-ELSE. An additional move will be + needed to implement that. */ + if (!TARGET_Z15 && reload_completed && !rtx_equal_p (dst, then) + && !rtx_equal_p (dst, els)) + *total += COSTS_N_INSNS (1) / 2; - return true; + /* A minor penalty for constants we cannot directly handle. */ + if ((CONST_INT_P (then) || CONST_INT_P (els)) + && (!TARGET_Z13 || MEM_P (dst) + || (CONST_INT_P (then) && !satisfies_constraint_K (then)) + || (CONST_INT_P (els) && !satisfies_constraint_K (els)))) + *total += COSTS_N_INSNS (1) / 2; + + /* A store on condition can only handle register src operands. */ + if (MEM_P (dst) && (!REG_P (then) || !REG_P (els))) + *total += COSTS_N_INSNS (1) / 2; + + return true; + } + default: + break; + } + + switch (GET_CODE (dest)) + { + case SUBREG: + if (!REG_P (SUBREG_REG (dest))) + *total += rtx_cost (SUBREG_REG (src), VOIDmode, SET, 0, speed); + /* fallthrough */ + case REG: + /* If this is a VR -> VR copy, count the number of + registers. */ + if (VECTOR_MODE_P (GET_MODE (dest)) && REG_P (src)) + { + int nregs = s390_hard_regno_nregs (VR0_REGNUM, GET_MODE (dest)); + *total = COSTS_N_INSNS (nregs); + } + /* Same for GPRs. */ + else if (REG_P (src)) + { + int nregs + = s390_hard_regno_nregs (GPR0_REGNUM, GET_MODE (dest)); + *total = COSTS_N_INSNS (nregs); + } + else + /* Otherwise just cost the src. */ + *total += rtx_cost (src, mode, SET, 1, speed); + return true; + case MEM: { + rtx address = XEXP (dest, 0); + rtx tmp; + HOST_WIDE_INT tmp2; + if (s390_loadrelative_operand_p (address, &tmp, &tmp2)) + *total = COSTS_N_INSNS (1); + else + *total = s390_address_cost (address, mode, 0, speed); + return true; + } + default: + /* Not handled for now, assume default costs. */ + *total = COSTS_N_INSNS (1); + return false; + } + + return false; } case IOR: @@ -6520,7 +6601,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src) /* Emit a strict_low_part pattern if possible. */ if (smode_bsize == bitsize && bitpos == mode_bsize - smode_bsize) { - rtx low_dest = gen_lowpart (smode, dest); + rtx low_dest = s390_gen_lowpart_subreg (smode, dest); rtx low_src = gen_lowpart (smode, src); switch (smode) @@ -8520,6 +8601,7 @@ s390_issue_rate (void) case PROCESSOR_2827_ZEC12: case PROCESSOR_2964_Z13: case PROCESSOR_3906_Z14: + case PROCESSOR_8561_Z15: case PROCESSOR_3931_Z16: default: return 1; @@ -15395,6 +15477,21 @@ s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop) if (s390_tune < PROCESSOR_2097_Z10) return nunroll; + if (unroll_only_small_loops) + { + /* Only unroll loops smaller than or equal to 12 insns. */ + const unsigned int small_threshold = 12; + + if (loop->ninsns > small_threshold) + return 0; + + /* ???: Make this dependent on the type of registers in + the loop. Increase the limit for vector registers. */ + const unsigned int max_insns = optimize >= 3 ? 36 : 24; + + nunroll = MIN (nunroll, max_insns / loop->ninsns); + } + /* Count the number of memory references within the loop body. */ bbs = get_loop_body (loop); subrtx_iterator::array_type array; @@ -15469,6 +15566,19 @@ static void s390_override_options_after_change (void) { s390_default_align (&global_options); + + /* Explicit -funroll-loops turns -munroll-only-small-loops off. */ + if ((OPTION_SET_P (flag_unroll_loops) && flag_unroll_loops) + || (OPTION_SET_P (flag_unroll_all_loops) + && flag_unroll_all_loops)) + { + if (!OPTION_SET_P (unroll_only_small_loops)) + unroll_only_small_loops = 0; + if (!OPTION_SET_P (flag_cunroll_grow_size)) + flag_cunroll_grow_size = 1; + } + else if (!OPTION_SET_P (flag_cunroll_grow_size)) + flag_cunroll_grow_size = flag_peel_loops || optimize >= 3; } static void @@ -15678,6 +15788,9 @@ s390_option_override_internal (struct gcc_options *opts, /* Set the default alignment. */ s390_default_align (opts); + /* Set unroll options. */ + s390_override_options_after_change (); + /* Call target specific restore function to do post-init work. At the moment, this just sets opts->x_s390_cost_pointer. */ s390_function_specific_restore (opts, opts_set, NULL); @@ -17067,6 +17180,8 @@ struct expand_vec_perm_d machine_mode vmode; unsigned char nelt; bool testing_p; + bool only_op0; + bool only_op1; }; /* Try to expand the vector permute operation described by D using the @@ -17134,7 +17249,9 @@ expand_perm_with_vpdi (const struct expand_vec_perm_d &d) if (d.perm[0] == 0 && d.perm[1] == 3) vpdi1_p = true; - if (d.perm[0] == 1 && d.perm[1] == 2) + if ((d.perm[0] == 1 && d.perm[1] == 2) + || (d.perm[0] == 1 && d.perm[1] == 0) + || (d.perm[0] == 3 && d.perm[1] == 2)) vpdi4_p = true; if (!vpdi1_p && !vpdi4_p) @@ -17146,15 +17263,107 @@ expand_perm_with_vpdi (const struct expand_vec_perm_d &d) op0_reg = force_reg (GET_MODE (d.op0), d.op0); op1_reg = force_reg (GET_MODE (d.op1), d.op1); + /* If we only reference either of the operands in + the permute mask, just use one of them. */ + if (d.only_op0) + op1_reg = op0_reg; + else if (d.only_op1) + op0_reg = op1_reg; + if (vpdi1_p) emit_insn (gen_vpdi1 (d.vmode, d.target, op0_reg, op1_reg)); - if (vpdi4_p) emit_insn (gen_vpdi4 (d.vmode, d.target, op0_reg, op1_reg)); return true; } +/* Helper that checks if a vector permutation mask D + represents a reversal of the vector's elements. */ +static inline bool +is_reverse_perm_mask (const struct expand_vec_perm_d &d) +{ + for (int i = 0; i < d.nelt; i++) + if (d.perm[i] != d.nelt - i - 1) + return false; + return true; +} + +/* The case of reversing a four-element vector [0, 1, 2, 3] + can be handled by first permuting the doublewords + [2, 3, 0, 1] and subsequently rotating them by 32 bits. */ +static bool +expand_perm_with_rot (const struct expand_vec_perm_d &d) +{ + if (d.nelt != 4) + return false; + + if (d.op0 == d.op1 && is_reverse_perm_mask (d)) + { + if (d.testing_p) + return true; + + rtx tmp = gen_reg_rtx (d.vmode); + rtx op0_reg = force_reg (GET_MODE (d.op0), d.op0); + + emit_insn (gen_vpdi4_2 (d.vmode, tmp, op0_reg, op0_reg)); + if (d.vmode == V4SImode) + emit_insn (gen_rotlv4si3_di (d.target, tmp)); + else if (d.vmode == V4SFmode) + emit_insn (gen_rotlv4sf3_di (d.target, tmp)); + + return true; + } + + return false; +} + +/* If we just reverse the elements, emit an eltswap if we have + vler/vster. */ +static bool +expand_perm_with_vster (const struct expand_vec_perm_d &d) +{ + if (TARGET_VXE2 && d.op0 == d.op1 && is_reverse_perm_mask (d) + && (d.vmode == V2DImode || d.vmode == V2DFmode + || d.vmode == V4SImode || d.vmode == V4SFmode + || d.vmode == V8HImode)) + { + if (d.testing_p) + return true; + + if (d.vmode == V2DImode) + emit_insn (gen_eltswapv2di (d.target, d.op0)); + else if (d.vmode == V2DFmode) + emit_insn (gen_eltswapv2df (d.target, d.op0)); + else if (d.vmode == V4SImode) + emit_insn (gen_eltswapv4si (d.target, d.op0)); + else if (d.vmode == V4SFmode) + emit_insn (gen_eltswapv4sf (d.target, d.op0)); + else if (d.vmode == V8HImode) + emit_insn (gen_eltswapv8hi (d.target, d.op0)); + return true; + } + return false; +} + +/* If we reverse a byte-vector this is the same as + byte reversing it which can be done with vstbrq. */ +static bool +expand_perm_with_vstbrq (const struct expand_vec_perm_d &d) +{ + if (TARGET_VXE2 && d.op0 == d.op1 && is_reverse_perm_mask (d) + && d.vmode == V16QImode) + { + if (d.testing_p) + return true; + + emit_insn (gen_eltswapv16qi (d.target, d.op0)); + return true; + } + return false; +} + + /* Try to find the best sequence for the vector permute operation described by D. Return true if the operation could be expanded. */ @@ -17164,9 +17373,18 @@ vectorize_vec_perm_const_1 (const struct expand_vec_perm_d &d) if (expand_perm_with_merge (d)) return true; + if (expand_perm_with_vster (d)) + return true; + + if (expand_perm_with_vstbrq (d)) + return true; + if (expand_perm_with_vpdi (d)) return true; + if (expand_perm_with_rot (d)) + return true; + return false; } @@ -17196,17 +17414,27 @@ s390_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode, gcc_assert (VECTOR_MODE_P (d.vmode)); d.nelt = nelt = GET_MODE_NUNITS (d.vmode); d.testing_p = target == NULL_RTX; + d.only_op0 = false; + d.only_op1 = false; gcc_assert (target == NULL_RTX || REG_P (target)); gcc_assert (sel.length () == nelt); + unsigned int highest = 0, lowest = 2 * nelt - 1; for (i = 0; i < nelt; i++) { unsigned char e = sel[i]; + lowest = MIN (lowest, e); + highest = MAX (highest, e); gcc_assert (e < 2 * nelt); d.perm[i] = e; } + if (lowest < nelt && highest < nelt) + d.only_op0 = true; + else if (lowest >= nelt && highest >= nelt) + d.only_op1 = true; + return vectorize_vec_perm_const_1 (d); } diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 2e1bc71..be56621 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -247,10 +247,6 @@ enum processor_flags /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() s390_cpu_cpp_builtins (pfile) -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS s390_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO s390_d_register_target_info - #ifdef DEFAULT_TARGET_64BIT #define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP \ | MASK_OPT_HTM | MASK_OPT_VX) @@ -705,7 +701,7 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* Define the dwarf register mapping. v16-v31 -> 68-83 rX -> X otherwise */ -#define DBX_REGISTER_NUMBER(regno) \ +#define DEBUGGER_REGNO(regno) \ (((regno) >= 38 && (regno) <= 53) ? (regno) + 30 : (regno)) /* Frame registers. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 55c0064..962927c 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -153,7 +153,6 @@ UNSPEC_VEC_VMALO UNSPEC_VEC_GATHER - UNSPEC_VEC_EXTRACT UNSPEC_VEC_INSERT_AND_ZERO UNSPEC_VEC_LOAD_BNDRY UNSPEC_VEC_LOAD_LEN @@ -1744,8 +1743,8 @@ && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])" [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (unspec:DI [(match_dup 5) (const_int 1)] - UNSPEC_VEC_EXTRACT))] + (set (match_dup 3) (vec_select:DI (match_dup 5) + (parallel [(const_int 1)])))] { operands[2] = operand_subword (operands[0], 0, 0, TImode); operands[3] = operand_subword (operands[0], 1, 0, TImode); @@ -1971,11 +1970,12 @@ "TARGET_ZARCH" "#" "&& reload_completed" - [(set (match_dup 2) (match_dup 3)) + [(set (match_dup 2) (match_dup 4)) (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32))) - (set (strict_low_part (match_dup 2)) (match_dup 4))] + (set (strict_low_part (match_dup 3)) (match_dup 5))] "operands[2] = gen_lowpart (SImode, operands[0]); - s390_split_access_reg (operands[1], &operands[4], &operands[3]);") + operands[3] = s390_gen_lowpart_subreg (SImode, operands[0]); + s390_split_access_reg (operands[1], &operands[5], &operands[4]);") ; Splitters for storing TLS pointer to %a0:DI. @@ -2522,13 +2522,14 @@ [(set (match_dup 0) (match_dup 2))] "operands[2] = get_pool_constant (operands[1]);") + ; -; movstrictqi instruction pattern(s). +; movstrict instruction pattern(s). ; (define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d,d")) - (match_operand:QI 1 "memory_operand" "R,T"))] + [(set (strict_low_part (match_operand:QI 0 "subreg_register_operand" "+d,d")) + (match_operand:QI 1 "memory_operand" "R,T"))] "" "@ ic\t%0,%1 @@ -2537,13 +2538,9 @@ (set_attr "cpu_facility" "*,longdisp") (set_attr "z10prop" "z10_super_E1,z10_super_E1")]) -; -; movstricthi instruction pattern(s). -; - (define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d")) - (match_operand:HI 1 "memory_operand" "Q,S")) + [(set (strict_low_part (match_operand:HI 0 "subreg_register_operand" "+d,d")) + (match_operand:HI 1 "memory_operand" "Q,S")) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -2553,13 +2550,9 @@ (set_attr "cpu_facility" "*,longdisp") (set_attr "z10prop" "z10_super_E1,z10_super_E1")]) -; -; movstrictsi instruction pattern(s). -; - (define_insn "movstrictsi" - [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d")) - (match_operand:SI 1 "general_operand" "d,R,T,t"))] + [(set (strict_low_part (match_operand:SI 0 "subreg_register_operand" "+d,d,d,d")) + (match_operand:SI 1 "general_operand" "d,R,T,t"))] "TARGET_ZARCH" "@ lr\t%0,%1 @@ -5019,7 +5012,7 @@ (parallel [(set (strict_low_part (match_dup 2)) (match_dup 1)) (clobber (reg:CC CC_REGNUM))])] - "operands[2] = gen_lowpart (HImode, operands[0]);") + "operands[2] = s390_gen_lowpart_subreg (HImode, operands[0]);") (define_insn_and_split "*zero_extendqisi2_31" [(set (match_operand:SI 0 "register_operand" "=&d") @@ -5029,7 +5022,7 @@ "&& reload_completed" [(set (match_dup 0) (const_int 0)) (set (strict_low_part (match_dup 2)) (match_dup 1))] - "operands[2] = gen_lowpart (QImode, operands[0]);") + "operands[2] = s390_gen_lowpart_subreg (QImode, operands[0]);") ; ; zero_extendqihi2 instruction pattern(s). @@ -5061,7 +5054,7 @@ "&& reload_completed" [(set (match_dup 0) (const_int 0)) (set (strict_low_part (match_dup 2)) (match_dup 1))] - "operands[2] = gen_lowpart (QImode, operands[0]);") + "operands[2] = s390_gen_lowpart_subreg (QImode, operands[0]);") ; ; fixuns_trunc(dd|td|sf|df|tf)(si|di)2 expander diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt index 9e8d3bf..c375b9c 100644 --- a/gcc/config/s390/s390.opt +++ b/gcc/config/s390/s390.opt @@ -321,3 +321,7 @@ and the default behavior is to emit separate multiplication and addition instructions for long doubles in vector registers, because measurements show that this improves performance. This option allows overriding it for testing purposes. + +munroll-only-small-loops +Target Undocumented Var(unroll_only_small_loops) Init(0) Save +; Use conservative small loop unrolling. diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 6247298..dde74af 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -270,11 +270,13 @@ (match_operand:V_128 1 "register_operand" ""))] "TARGET_VX && GENERAL_REG_P (operands[0]) && VECTOR_REG_P (operands[1])" [(set (match_dup 2) - (unspec:DI [(subreg:V2DI (match_dup 1) 0) - (const_int 0)] UNSPEC_VEC_EXTRACT)) + (vec_select:DI + (subreg:V2DI (match_dup 1) 0) + (parallel [(const_int 0)]))) (set (match_dup 3) - (unspec:DI [(subreg:V2DI (match_dup 1) 0) - (const_int 1)] UNSPEC_VEC_EXTRACT))] + (vec_select:DI + (subreg:V2DI (match_dup 1) 0) + (parallel [(const_int 1)])))] { operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode); operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode); @@ -511,22 +513,24 @@ [(set_attr "op_type" "VRS")]) -; FIXME: Support also vector mode operands for 0 -; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :( -; This is used via RTL standard name as well as for expanding the builtin +;; FIXME: Support also vector mode operands for 0 +;; This is used via RTL standard name as well as for expanding the builtin (define_expand "vec_extract<mode><non_vec_l>" - [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "") - (unspec:<non_vec> [(match_operand:V 1 "register_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")] - UNSPEC_VEC_EXTRACT))] - "TARGET_VX") + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "") + (vec_select:<non_vec> + (match_operand:V 1 "register_operand" "") + (parallel + [(match_operand:SI 2 "nonmemory_operand" "")])))] + "TARGET_VX" +) ; vlgvb, vlgvh, vlgvf, vlgvg, vsteb, vsteh, vstef, vsteg (define_insn "*vec_extract<mode>" - [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,R") - (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v,v") - (match_operand:SI 2 "nonmemory_operand" "an,I")] - UNSPEC_VEC_EXTRACT))] + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d,R") + (vec_select:<non_vec> + (match_operand:V 1 "nonmemory_operand" "v,v") + (parallel + [(match_operand:SI 2 "nonmemory_operand" "an,I")])))] "TARGET_VX && (!CONST_INT_P (operands[2]) || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))" @@ -537,11 +541,11 @@ ; vlgvb, vlgvh, vlgvf, vlgvg (define_insn "*vec_extract<mode>_plus" - [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d") - (unspec:<non_vec> [(match_operand:V 1 "register_operand" "v") - (plus:SI (match_operand:SI 2 "nonmemory_operand" "a") - (match_operand:SI 3 "const_int_operand" "n"))] - UNSPEC_VEC_EXTRACT))] + [(set (match_operand:<non_vec> 0 "nonimmediate_operand" "=d") + (vec_select:<non_vec> + (match_operand:V 1 "register_operand" "v") + (plus:SI (match_operand:SI 2 "nonmemory_operand" "a") + (parallel [(match_operand:SI 3 "const_int_operand" "n")]))))] "TARGET_VX" "vlgv<bhfgq>\t%0,%v1,%Y3(%2)" [(set_attr "op_type" "VRS")]) @@ -797,6 +801,17 @@ "vpdi\t%v0,%v1,%v2,4" [(set_attr "op_type" "VRR")]) +; Second DW of op1 and first DW of op2 (when interpreted as 2-element vector). +(define_insn "@vpdi4_2<mode>" + [(set (match_operand:V_HW_4 0 "register_operand" "=v") + (vec_select:V_HW_4 + (vec_concat:<vec_2x_nelts> + (match_operand:V_HW_4 1 "register_operand" "v") + (match_operand:V_HW_4 2 "register_operand" "v")) + (parallel [(const_int 2) (const_int 3) (const_int 4) (const_int 5)])))] + "TARGET_VX" + "vpdi\t%v0,%v1,%v2,4" + [(set_attr "op_type" "VRR")]) (define_insn "*vmrhb" [(set (match_operand:V16QI 0 "register_operand" "=v") @@ -1255,6 +1270,23 @@ "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) +; verllg for V4SI/V4SF. This swaps the first and the second two +; elements of a vector and is only valid in that context. +(define_expand "rotl<mode>3_di" + [ + (set (match_dup 2) + (subreg:V2DI (match_operand:V_HW_4 1) 0)) + (set (match_dup 3) + (rotate:V2DI + (match_dup 2) + (const_int 32))) + (set (match_operand:V_HW_4 0) + (subreg:V_HW_4 (match_dup 3) 0))] + "TARGET_VX" + { + operands[2] = gen_reg_rtx (V2DImode); + operands[3] = gen_reg_rtx (V2DImode); + }) ; Shift each element by corresponding vector element diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md index 98ee08b..e4bb514 100644 --- a/gcc/config/s390/vx-builtins.md +++ b/gcc/config/s390/vx-builtins.md @@ -440,12 +440,13 @@ (define_insn "vec_scatter_element<V_HW_4:mode>_DI" [(set (mem:<non_vec> (plus:DI (zero_extend:DI - (unspec:SI [(match_operand:V4SI 1 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_EXTRACT)) - (match_operand:SI 2 "address_operand" "ZQ"))) - (unspec:<non_vec> [(match_operand:V_HW_4 0 "register_operand" "v") - (match_dup 3)] UNSPEC_VEC_EXTRACT))] + (vec_select:SI + (match_operand:V4SI 1 "register_operand" "v") + (parallel [(match_operand:QI 3 "const_mask_operand" "C")]))) + (match_operand:SI 2 "address_operand" "ZQ"))) + (vec_select:<non_vec> + (match_operand:V_HW_4 0 "register_operand" "v") + (parallel [(match_dup 3)])))] "TARGET_VX && TARGET_64BIT && UINTVAL (operands[3]) < 4" "vscef\t%v0,%O2(%v1,%R2),%3" [(set_attr "op_type" "VRV")]) @@ -455,12 +456,13 @@ (define_insn "vec_scatter_element<V_HW_2:mode>_SI" [(set (mem:<non_vec> (plus:SI (subreg:SI - (unspec:<non_vec_int> [(match_operand:V_HW_2 1 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_EXTRACT) 4) - (match_operand:SI 2 "address_operand" "ZQ"))) - (unspec:<non_vec> [(match_operand:V_HW_2 0 "register_operand" "v") - (match_dup 3)] UNSPEC_VEC_EXTRACT))] + (vec_select:<non_vec_int> + (match_operand:<TOINTVEC> 1 "register_operand" "v") + (parallel [(match_operand:QI 3 "const_mask_operand" "C")])) 4) + (match_operand:SI 2 "address_operand" "ZQ"))) + (vec_select:<non_vec> + (match_operand:V_HW_2 0 "register_operand" "v") + (parallel [(match_dup 3)])))] "TARGET_VX && !TARGET_64BIT && UINTVAL (operands[3]) < GET_MODE_NUNITS (<V_HW_2:MODE>mode)" "vsce<V_HW_2:bhfgq>\t%v0,%O2(%v1,%R2),%3" [(set_attr "op_type" "VRV")]) @@ -469,13 +471,14 @@ ; vscef, vsceg (define_insn "vec_scatter_element<mode>_<non_vec_int>" [(set (mem:<non_vec> - (plus:<non_vec_int> (unspec:<non_vec_int> - [(match_operand:<TOINTVEC> 1 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_EXTRACT) - (match_operand:DI 2 "address_operand" "ZQ"))) - (unspec:<non_vec> [(match_operand:V_HW_32_64 0 "register_operand" "v") - (match_dup 3)] UNSPEC_VEC_EXTRACT))] + (plus:<non_vec_int> + (vec_select:<non_vec_int> + (match_operand:<TOINTVEC> 1 "register_operand" "v") + (parallel [(match_operand:QI 3 "const_mask_operand" "C")])) + (match_operand:DI 2 "address_operand" "ZQ"))) + (vec_select:<non_vec> + (match_operand:V_HW_32_64 0 "register_operand" "v") + (parallel [(match_dup 3)])))] "TARGET_VX && UINTVAL (operands[3]) < GET_MODE_NUNITS (<V_HW_32_64:MODE>mode)" "vsce<bhfgq>\t%v0,%O2(%v1,%R2),%3" [(set_attr "op_type" "VRV")]) @@ -1889,9 +1892,11 @@ (const_int VEC_RND_CURRENT)] UNSPEC_VEC_VFLR)) (set (match_operand:SF 1 "memory_operand" "") - (unspec:SF [(match_dup 2) (const_int 0)] UNSPEC_VEC_EXTRACT)) + (vec_select:SF (match_dup 2) + (parallel [(const_int 0)]))) (set (match_dup 3) - (unspec:SF [(match_dup 2) (const_int 2)] UNSPEC_VEC_EXTRACT))] + (vec_select:SF (match_dup 2) + (parallel [(const_int 2)])))] "TARGET_VX" { operands[2] = gen_reg_rtx (V4SFmode); @@ -2181,6 +2186,68 @@ vster<bhfgq>\t%v1,%v0" [(set_attr "op_type" "*,VRX,VRX")]) +; The emulation pattern below will also accept +; vst (eltswap (vl)) +; i.e. both operands in memory, which reload needs to fix. +; Split into +; vl +; vster (=vst (eltswap)) +; since we prefer vster over vler as long as the latter +; does not support alignment hints. +(define_split + [(set (match_operand:VEC_HW 0 "memory_operand" "") + (unspec:VEC_HW [(match_operand:VEC_HW 1 "memory_operand" "")] + UNSPEC_VEC_ELTSWAP))] + "TARGET_VXE2 && can_create_pseudo_p ()" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) + (unspec:VEC_HW [(match_dup 2)] UNSPEC_VEC_ELTSWAP))] +{ + operands[2] = gen_reg_rtx (<MODE>mode); +}) + + +; Swapping v2df/v2di can be done via vpdi on z13 and z14. +(define_split + [(set (match_operand:V_HW_2 0 "register_operand" "") + (unspec:V_HW_2 [(match_operand:V_HW_2 1 "register_operand" "")] + UNSPEC_VEC_ELTSWAP))] + "TARGET_VX && can_create_pseudo_p ()" + [(set (match_operand:V_HW_2 0 "register_operand" "=v") + (vec_select:V_HW_2 + (vec_concat:<vec_2x_nelts> + (match_operand:V_HW_2 1 "register_operand" "v") + (match_dup 1)) + (parallel [(const_int 1) (const_int 2)])))] +) + + +; Swapping v4df/v4si can be done via vpdi and rot. +(define_split + [(set (match_operand:V_HW_4 0 "register_operand" "") + (unspec:V_HW_4 [(match_operand:V_HW_4 1 "register_operand" "")] + UNSPEC_VEC_ELTSWAP))] + "TARGET_VX && can_create_pseudo_p ()" + [(set (match_dup 2) + (vec_select:V_HW_4 + (vec_concat:<vec_2x_nelts> + (match_dup 1) + (match_dup 1)) + (parallel [(const_int 2) (const_int 3) (const_int 4) (const_int 5)]))) + (set (match_dup 3) + (subreg:V2DI (match_dup 2) 0)) + (set (match_dup 4) + (rotate:V2DI + (match_dup 3) + (const_int 32))) + (set (match_operand:V_HW_4 0) + (subreg:V_HW_4 (match_dup 4) 0))] +{ + operands[2] = gen_reg_rtx (<MODE>mode); + operands[3] = gen_reg_rtx (V2DImode); + operands[4] = gen_reg_rtx (V2DImode); +}) + ; z15 has instructions for doing element reversal from mem to reg ; or the other way around. For reg to reg or on pre z15 machines ; we have to emulate it with vector permute. @@ -2259,10 +2326,10 @@ ; *a = vec_revb (b)[1]; get-element-bswap-4.c ; vstebrh, vstebrf, vstebrg (define_insn "*vec_extract_bswap_vec<mode>" - [(set (match_operand:<non_vec> 0 "memory_operand" "=R") - (unspec:<non_vec> [(bswap:V_HW_HSD (match_operand:V_HW_HSD 1 "register_operand" "v")) - (match_operand:SI 2 "const_int_operand" "C")] - UNSPEC_VEC_EXTRACT))] + [(set (match_operand:<non_vec> 0 "memory_operand" "=R") + (vec_select:<non_vec> + (bswap:V_HW_HSD (match_operand:V_HW_HSD 1 "register_operand" "v")) + (parallel [(match_operand:SI 2 "const_int_operand" "C")])))] "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)" "vstebr<bhfgq>\t%v1,%0,%2" [(set_attr "op_type" "VRX")]) @@ -2271,11 +2338,11 @@ ; *a = __builtin_bswap32 (b[1]); get-element-bswap-2.c ; vstebrh, vstebrf, vstebrg (define_insn "*vec_extract_bswap_elem<mode>" - [(set (match_operand:<non_vec> 0 "memory_operand" "=R") + [(set (match_operand:<non_vec> 0 "memory_operand" "=R") (bswap:<non_vec> - (unspec:<non_vec> [(match_operand:V_HW_HSD 1 "register_operand" "v") - (match_operand:SI 2 "const_int_operand" "C")] - UNSPEC_VEC_EXTRACT)))] + (vec_select:<non_vec> + (match_operand:V_HW_HSD 1 "register_operand" "v") + (parallel [(match_operand:SI 2 "const_int_operand" "C")]))))] "TARGET_VXE2 && UINTVAL (operands[2]) < GET_MODE_NUNITS (<V_HW_HSD:MODE>mode)" "vstebr<bhfgq>\t%v1,%0,%2" [(set_attr "op_type" "VRX")]) diff --git a/gcc/config/sh/elf.h b/gcc/config/sh/elf.h index afb3bc3..8530c15 100644 --- a/gcc/config/sh/elf.h +++ b/gcc/config/sh/elf.h @@ -61,15 +61,12 @@ along with GCC; see the file COPYING3. If not see #define LINK_EMUL_PREFIX "sh%{ml:l}elf" #endif -#define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO) +#define DEBUGGER_REGNO(REGNO) SH_DEBUGGER_REGNO (REGNO) #undef ASM_GENERATE_INTERNAL_LABEL #define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \ sprintf ((STRING), "*%s%s%ld", LOCAL_LABEL_PREFIX, (PREFIX), (long)(NUM)) -#define DBX_LINES_FUNCTION_RELATIVE 1 -#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - #undef STARTFILE_SPEC #define STARTFILE_SPEC \ "%{!shared: crt1.o%s} crti.o%s \ diff --git a/gcc/config/sh/linux.h b/gcc/config/sh/linux.h index d96d077..77a8373 100644 --- a/gcc/config/sh/linux.h +++ b/gcc/config/sh/linux.h @@ -111,11 +111,11 @@ along with GCC; see the file COPYING3. If not see in MD_FALLBACK_FRAME_STATE_FOR and its content will be read with _Unwind_GetGR which uses dwarf_reg_size_table to get the size of the register. So the entry of dwarf_reg_size_table corresponding to - this slot must be set. To do this, we redefine DBX_REGISTER_NUMBER + this slot must be set. To do this, we redefine DEBUGGER_REGNO so as to return itself for 16. */ -#undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(REGNO) \ - (((REGNO) == 16) ? 16 : SH_DBX_REGISTER_NUMBER (REGNO)) +#undef DEBUGGER_REGNO +#define DEBUGGER_REGNO(REGNO) \ + (((REGNO) == 16) ? 16 : SH_DEBUGGER_REGNO (REGNO)) /* Install the __sync libcalls. */ #undef TARGET_INIT_LIBFUNCS diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 4f209d2..3f60e15 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1654,14 +1654,14 @@ extern bool current_function_interrupt; fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v)); \ } -/* DBX register number for a given compiler register number. */ +/* Debugger register number for a given compiler register number. */ /* GDB has FPUL at 23 and FP0 at 25, so we must add one to all FP registers to match gdb. */ /* expand_builtin_init_dwarf_reg_sizes uses this to test if a register exists, so we should return -1 for invalid register numbers. */ -#define DBX_REGISTER_NUMBER(REGNO) SH_DBX_REGISTER_NUMBER (REGNO) +#define DEBUGGER_REGNO(REGNO) SH_DEBUGGER_REGNO (REGNO) -#define SH_DBX_REGISTER_NUMBER(REGNO) \ +#define SH_DEBUGGER_REGNO(REGNO) \ (IN_RANGE ((REGNO), \ (unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \ FIRST_GENERAL_REG + 15U) \ diff --git a/gcc/config/sol2-d.cc b/gcc/config/sol2-d.cc index 9caa82e..0ace79d 100644 --- a/gcc/config/sol2-d.cc +++ b/gcc/config/sol2-d.cc @@ -18,9 +18,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" -#include "memmodel.h" -#include "tm_p.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index e22c70c..fc70330 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -498,11 +498,7 @@ along with GCC; see the file COPYING3. If not see #define AS_NEEDS_DASH_FOR_PIPED_INPUT -/* The Solaris assembler cannot grok .stabd directives. */ -#undef NO_DBX_BNSYM_ENSYM -#define NO_DBX_BNSYM_ENSYM 1 #endif - /* Solaris has an implementation of __enable_execute_stack. */ #define HAVE_ENABLE_EXECUTE_STACK diff --git a/gcc/config/sparc/freebsd.h b/gcc/config/sparc/freebsd.h index 98319c5..73850a3 100644 --- a/gcc/config/sparc/freebsd.h +++ b/gcc/config/sparc/freebsd.h @@ -109,12 +109,6 @@ along with GCC; see the file COPYING3. If not see /************************[ Debugger stuff ]*********************************/ -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#undef DBX_CONTIN_CHAR -#define DBX_CONTIN_CHAR '?' - /* DWARF bits. */ /* Follow Irix 6 and not the Dwarf2 draft in using 64-bit offsets. diff --git a/gcc/config/sparc/netbsd-elf.h b/gcc/config/sparc/netbsd-elf.h index af194df..bee71fc 100644 --- a/gcc/config/sparc/netbsd-elf.h +++ b/gcc/config/sparc/netbsd-elf.h @@ -46,11 +46,6 @@ along with GCC; see the file COPYING3. If not see #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "long int" -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ -#undef DBX_CONTIN_CHAR -#define DBX_CONTIN_CHAR '?' - #undef LOCAL_LABEL_PREFIX #define LOCAL_LABEL_PREFIX "." diff --git a/gcc/config/sparc/sparc-d.cc b/gcc/config/sparc/sparc-d.cc index 1f3a966..f8a3cf3 100644 --- a/gcc/config/sparc/sparc-d.cc +++ b/gcc/config/sparc/sparc-d.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tm_d.h" #include "d/d-target.h" #include "d/d-target-def.h" diff --git a/gcc/config/sparc/sparc-d.h b/gcc/config/sparc/sparc-d.h new file mode 100644 index 0000000..b9d8ccf --- /dev/null +++ b/gcc/config/sparc/sparc-d.h @@ -0,0 +1,24 @@ +/* Definitions for the D front end on the SPARC architecture. + Copyright (C) 2022 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Routines implemented in sparc-d.cc */ +extern void sparc_d_target_versions (void); +extern void sparc_d_register_target_info (void); + +/* Target hooks for D language. */ +#define TARGET_D_CPU_VERSIONS sparc_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO sparc_d_register_target_info diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index f9e1c74..4ddd00c 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -112,8 +112,4 @@ unsigned int sparc_regmode_natural_size (machine_mode); extern rtl_opt_pass *make_pass_work_around_errata (gcc::context *); -/* Routines implemented in sparc-d.cc */ -extern void sparc_d_target_versions (void); -extern void sparc_d_register_target_info (void); - #endif /* __SPARC_PROTOS_H__ */ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 2e17fca..155e1da 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -27,10 +27,6 @@ along with GCC; see the file COPYING3. If not see #define TARGET_CPU_CPP_BUILTINS() sparc_target_macros () -/* Target hooks for D language. */ -#define TARGET_D_CPU_VERSIONS sparc_d_target_versions -#define TARGET_D_REGISTER_CPU_TARGET_INFO sparc_d_register_target_info - /* Specify this in a cover file to provide bi-architecture (32/64) support. */ /* #define SPARC_BI_ARCH */ @@ -1510,14 +1506,6 @@ do { \ #define ADDITIONAL_REGISTER_NAMES \ {{"ccr", SPARC_ICC_REG}, {"cc", SPARC_ICC_REG}} -/* On Sun 4, this limit is 2048. We use 1000 to be safe, since the length - can run past this up to a continuation point. Once we used 1500, but - a single entry in C++ can run more than 500 bytes, due to the length of - mangled symbol names. dbxout.cc should really be fixed to do - continuations when they are actually needed instead of trying to - guess... */ -#define DBX_CONTIN_LENGTH 1000 - /* This is how to output a command to make the user-level label named NAME defined for reference from other files. */ diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc index f44e23d..28c1af5 100644 --- a/gcc/config/vax/vax.cc +++ b/gcc/config/vax/vax.cc @@ -247,9 +247,6 @@ static void vax_file_start (void) { default_file_start (); - - if (write_symbols == DBX_DEBUG) - fprintf (asm_out_file, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR); } /* We can use the BSD C library routines for the libgcc calls that are diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h index 45c0e75..12c51e5 100644 --- a/gcc/config/vax/vax.h +++ b/gcc/config/vax/vax.h @@ -508,27 +508,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES }; "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", \ "psl" } -/* This is BSD, so it wants DBX format. */ - -#define DBX_DEBUGGING_INFO 1 - -/* Do not break .stabs pseudos into continuations. */ - -#define DBX_CONTIN_LENGTH 0 - -/* This is the char to use for continuation (in case we need to turn - continuation back on). */ - -#define DBX_CONTIN_CHAR '?' - -/* Don't use the `xsfoo;' construct in DBX output; this system - doesn't support it. */ - -#define DBX_NO_XREFS - -/* Output the .stabs for a C `static' variable in the data section. */ -#define DBX_STATIC_STAB_DATA_SECTION - /* VAX specific: which type character is used for type double? */ #define ASM_DOUBLE_CHAR (TARGET_G_FLOAT ? 'g' : 'd') diff --git a/gcc/config/visium/visium.h b/gcc/config/visium/visium.h index e981924..d7de116 100644 --- a/gcc/config/visium/visium.h +++ b/gcc/config/visium/visium.h @@ -1491,7 +1491,7 @@ do \ This describes how to specify debugging information. mda is known to GDB, but not to GCC. */ -#define DBX_REGISTER_NUMBER(REGNO) \ +#define DEBUGGER_REGNO(REGNO) \ ((REGNO) > MDB_REGNUM ? (REGNO) + 1 : (REGNO)) /* `DEBUGGER_AUTO_OFFSET (X)' @@ -1500,7 +1500,7 @@ do \ automatic variable having address X (an RTL expression). The default computation assumes that X is based on the frame-pointer and gives the offset from the frame-pointer. This is required for - targets that produce debugging output for DBX and allow the frame-pointer + targets that produce debugging output for debugger and allow the frame-pointer to be eliminated when the `-g' options is used. */ #define DEBUGGER_AUTO_OFFSET(X) \ (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) diff --git a/gcc/config/vx-common.h b/gcc/config/vx-common.h index aaae4f7..bc27684 100644 --- a/gcc/config/vx-common.h +++ b/gcc/config/vx-common.h @@ -94,8 +94,6 @@ along with GCC; see the file COPYING3. If not see #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG /* None of these other formats is supported. */ -#undef DBX_DEBUGGING_INFO -#undef XCOFF_DEBUGGING_INFO #undef VMS_DEBUGGING_INFO /* ------------------------ Misc configuration bits ---------------------- */ diff --git a/gcc/config/xtensa/elf.h b/gcc/config/xtensa/elf.h index 527bb4e..fbdccc4 100644 --- a/gcc/config/xtensa/elf.h +++ b/gcc/config/xtensa/elf.h @@ -81,7 +81,7 @@ along with GCC; see the file COPYING3. If not see /* Do not force "-fpic" for this target. */ #define XTENSA_ALWAYS_PIC 0 -#undef DBX_REGISTER_NUMBER +#undef DEBUGGER_REGNO /* Search for headers in $tooldir/arch/include and for libraries and startfiles in $tooldir/arch/lib. */ diff --git a/gcc/config/xtensa/linux.h b/gcc/config/xtensa/linux.h index edce618..540e4bf 100644 --- a/gcc/config/xtensa/linux.h +++ b/gcc/config/xtensa/linux.h @@ -67,5 +67,5 @@ along with GCC; see the file COPYING3. If not see /* Always enable "-fpic" for Xtensa Linux. */ #define XTENSA_ALWAYS_PIC 1 -#undef DBX_REGISTER_NUMBER +#undef DEBUGGER_REGNO diff --git a/gcc/config/xtensa/uclinux.h b/gcc/config/xtensa/uclinux.h index d47fd63..5fcf639 100644 --- a/gcc/config/xtensa/uclinux.h +++ b/gcc/config/xtensa/uclinux.h @@ -70,5 +70,5 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_LIBC_HAS_FUNCTION #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function -#undef DBX_REGISTER_NUMBER +#undef DEBUGGER_REGNO diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index e020a33..459e2aa 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -71,7 +71,7 @@ extern rtx xtensa_return_addr (int, rtx); #endif /* RTX_CODE */ extern void xtensa_setup_frame_addresses (void); -extern int xtensa_dbx_register_number (int); +extern int xtensa_debugger_regno (int); extern long compute_frame_size (poly_int64); extern bool xtensa_use_return_instruction_p (void); extern void xtensa_expand_prologue (void); diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index b673b67..93ac656 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -2430,7 +2430,7 @@ xtensa_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) /* Return the debugger register number to use for 'regno'. */ int -xtensa_dbx_register_number (int regno) +xtensa_debugger_regno (int regno) { int first = -1; diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index d51658a..0f3006d 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -216,7 +216,7 @@ along with GCC; see the file COPYING3. If not see #define FIRST_PSEUDO_REGISTER 36 /* Return the stabs register number to use for REGNO. */ -#define DBX_REGISTER_NUMBER(REGNO) xtensa_dbx_register_number (REGNO) +#define DEBUGGER_REGNO(REGNO) xtensa_debugger_regno (REGNO) /* 1 for registers that have pervasive standard uses and are not available for the register allocator. */ diff --git a/gcc/configure b/gcc/configure index 80498e6..39f7ed12 100755 --- a/gcc/configure +++ b/gcc/configure @@ -12680,21 +12680,6 @@ objext='.o' # Check whether --enable-sjlj-exceptions was given. if test "${enable_sjlj_exceptions+set}" = set; then : enableval=$enable_sjlj_exceptions; case $target in - *-*-hpux10*) - if test $enableval != yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: dwarf2 exceptions not supported, sjlj exceptions forced" >&5 -$as_echo "$as_me: WARNING: dwarf2 exceptions not supported, sjlj exceptions forced" >&2;} - enableval=yes - fi - ;; -esac -force_sjlj_exceptions=yes -else - case $target in - *-*-hpux10*) - force_sjlj_exceptions=yes - enableval=yes - ;; lm32*-*-*) force_sjlj_exceptions=yes enableval=yes @@ -13038,7 +13023,6 @@ fi tm_file="${tm_file} defaults.h" tm_p_file="${tm_p_file} tm-preds.h" -tm_d_file="${tm_d_file} defaults.h" host_xm_file="auto-host.h ansidecl.h ${host_xm_file}" build_xm_file="${build_auto} ansidecl.h ${build_xm_file}" # We don't want ansidecl.h in target files, write code there in ISO/GNU C. @@ -13433,13 +13417,9 @@ for f in $tm_p_file; do done tm_d_file_list= -tm_d_include_list="options.h insn-constants.h" +tm_d_include_list= for f in $tm_d_file; do case $f in - defaults.h ) - tm_d_file_list="${tm_d_file_list} \$(srcdir)/$f" - tm_d_include_list="${tm_d_include_list} $f" - ;; * ) tm_d_file_list="${tm_d_file_list} \$(srcdir)/config/$f" tm_d_include_list="${tm_d_include_list} config/$f" @@ -13577,6 +13557,12 @@ then BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' fi + +if test x$enable_fixincludes = xno; +then + STMP_FIXINC='' +fi + # Expand extra_headers to include complete path. # This substitutes for lots of t-* files. extra_headers_list= @@ -19703,7 +19689,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19706 "configure" +#line 19692 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19809,7 +19795,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 19812 "configure" +#line 19798 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -25107,38 +25093,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for stabs directive" >&5 -$as_echo_n "checking assembler for stabs directive... " >&6; } -if ${gcc_cv_as_stabs_directive+:} false; then : - $as_echo_n "(cached) " >&6 -else - gcc_cv_as_stabs_directive=no - if test x$gcc_cv_as != x; then - $as_echo '.stabs "gcc2_compiled.",60,0,0,0' > conftest.s - if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } - then - gcc_cv_as_stabs_directive=yes - else - echo "configure: failed program was" >&5 - cat conftest.s >&5 - fi - rm -f conftest.o conftest.s - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_stabs_directive" >&5 -$as_echo "$gcc_cv_as_stabs_directive" >&6; } -if test $gcc_cv_as_stabs_directive = yes; then - -$as_echo "#define HAVE_AS_STABS_DIRECTIVE 1" >>confdefs.h - -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for COMDAT group support (GNU as)" >&5 $as_echo_n "checking assembler for COMDAT group support (GNU as)... " >&6; } if ${gcc_cv_as_comdat_group+:} false; then : @@ -28190,41 +28144,6 @@ $as_echo "#define HAVE_AS_REF 1" >>confdefs.h fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for AIX DWARF location lists section support" >&5 -$as_echo_n "checking assembler for AIX DWARF location lists section support... " >&6; } -if ${gcc_cv_as_aix_dwloc+:} false; then : - $as_echo_n "(cached) " >&6 -else - gcc_cv_as_aix_dwloc=no - if test x$gcc_cv_as != x; then - $as_echo ' .dwsect 0xA0000 - Lframe..0: - .vbyte 4,Lframe..0 - ' > conftest.s - if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } - then - gcc_cv_as_aix_dwloc=yes - else - echo "configure: failed program was" >&5 - cat conftest.s >&5 - fi - rm -f conftest.o conftest.s - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_aix_dwloc" >&5 -$as_echo "$gcc_cv_as_aix_dwloc" >&6; } -if test $gcc_cv_as_aix_dwloc = yes; then - -$as_echo "#define HAVE_XCOFF_DWARF_EXTRAS 1" >>confdefs.h - -fi - ;; esac ;; @@ -29720,38 +29639,6 @@ $as_echo "#define HAVE_AS_WORKING_DWARF_N_FLAG 1" >>confdefs.h fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gstabs option" >&5 -$as_echo_n "checking assembler for --gstabs option... " >&6; } -if ${gcc_cv_as_gstabs_flag+:} false; then : - $as_echo_n "(cached) " >&6 -else - gcc_cv_as_gstabs_flag=no - if test x$gcc_cv_as != x; then - $as_echo "$insn" > conftest.s - if { ac_try='$gcc_cv_as $gcc_cv_as_flags --gstabs -o conftest.o conftest.s >&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } - then - gcc_cv_as_gstabs_flag=yes - else - echo "configure: failed program was" >&5 - cat conftest.s >&5 - fi - rm -f conftest.o conftest.s - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gstabs_flag" >&5 -$as_echo "$gcc_cv_as_gstabs_flag" >&6; } -if test $gcc_cv_as_gstabs_flag = yes; then - -$as_echo "#define HAVE_AS_GSTABS_DEBUG_FLAG 1" >>confdefs.h - -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --debug-prefix-map option" >&5 $as_echo_n "checking assembler for --debug-prefix-map option... " >&6; } if ${gcc_cv_as_debug_prefix_map_flag+:} false; then : diff --git a/gcc/configure.ac b/gcc/configure.ac index 819b490..50bb61c 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1802,19 +1802,6 @@ AC_ARG_ENABLE(sjlj-exceptions, [AS_HELP_STRING([--enable-sjlj-exceptions], [arrange to use setjmp/longjmp exception handling])], [case $target in - *-*-hpux10*) - if test $enableval != yes; then - AC_MSG_WARN([dwarf2 exceptions not supported, sjlj exceptions forced]) - enableval=yes - fi - ;; -esac -force_sjlj_exceptions=yes], -[case $target in - *-*-hpux10*) - force_sjlj_exceptions=yes - enableval=yes - ;; lm32*-*-*) force_sjlj_exceptions=yes enableval=yes @@ -2122,7 +2109,6 @@ AC_SUBST(HAVE_AUTO_BUILD) tm_file="${tm_file} defaults.h" tm_p_file="${tm_p_file} tm-preds.h" -tm_d_file="${tm_d_file} defaults.h" host_xm_file="auto-host.h ansidecl.h ${host_xm_file}" build_xm_file="${build_auto} ansidecl.h ${build_xm_file}" # We don't want ansidecl.h in target files, write code there in ISO/GNU C. @@ -2366,13 +2352,9 @@ for f in $tm_p_file; do done tm_d_file_list= -tm_d_include_list="options.h insn-constants.h" +tm_d_include_list= for f in $tm_d_file; do case $f in - defaults.h ) - tm_d_file_list="${tm_d_file_list} \$(srcdir)/$f" - tm_d_include_list="${tm_d_include_list} $f" - ;; * ) tm_d_file_list="${tm_d_file_list} \$(srcdir)/config/$f" tm_d_include_list="${tm_d_include_list} config/$f" @@ -2510,6 +2492,12 @@ then BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)' fi + +if test x$enable_fixincludes = xno; +then + STMP_FIXINC='' +fi + # Expand extra_headers to include complete path. # This substitutes for lots of t-* files. extra_headers_list= @@ -3519,11 +3507,6 @@ AC_DEFINE_UNQUOTED(HAVE_LD_ALIGNED_SHF_MERGE, [`if test $gcc_cv_ld_aligned_shf_merge = yes; then echo 1; else echo 0; fi`], [Define 0/1 if your linker supports the SHF_MERGE flag with section alignment > 1.]) -gcc_GAS_CHECK_FEATURE([stabs directive], gcc_cv_as_stabs_directive,, -[.stabs "gcc2_compiled.",60,0,0,0],, -[AC_DEFINE(HAVE_AS_STABS_DIRECTIVE, 1, - [Define if your assembler supports .stabs.])]) - gcc_GAS_CHECK_FEATURE([COMDAT group support (GNU as)], gcc_cv_as_comdat_group, [--fatal-warnings], @@ -5083,15 +5066,6 @@ LCF0: ],, [AC_DEFINE(HAVE_AS_REF, 1, [Define if your assembler supports .ref])]) - - gcc_GAS_CHECK_FEATURE([AIX DWARF location lists section support], - gcc_cv_as_aix_dwloc,, - [ .dwsect 0xA0000 - Lframe..0: - .vbyte 4,Lframe..0 - ],, - [AC_DEFINE(HAVE_XCOFF_DWARF_EXTRAS, 1, - [Define if your assembler supports AIX debug frame section label reference.])]) ;; esac ;; @@ -5735,12 +5709,6 @@ foo: fi fi - gcc_GAS_CHECK_FEATURE([--gstabs option], - gcc_cv_as_gstabs_flag, - [--gstabs], [$insn],, - [AC_DEFINE(HAVE_AS_GSTABS_DEBUG_FLAG, 1, -[Define if your assembler supports the --gstabs option.])]) - gcc_GAS_CHECK_FEATURE([--debug-prefix-map option], gcc_cv_as_debug_prefix_map_flag, [--debug-prefix-map /a=/b], [$insn],, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 083ead1..a11675e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,97 @@ +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * parser.cc (cp_parser_omp_clause_name): Handle doacross. + (cp_parser_omp_clause_depend_sink): Renamed to ... + (cp_parser_omp_clause_doacross_sink): ... this. Add depend_p + argument. Handle parsing of doacross(sink:omp_cur_iteration-1). Use + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of + OMP_CLAUSE_DEPEND_SINK_NEGATIVE, build OMP_CLAUSE_DOACROSS instead + of OMP_CLAUSE_DEPEND and set OMP_CLAUSE_DOACROSS_DEPEND flag on it. + (cp_parser_omp_clause_depend): Use OMP_CLAUSE_DOACROSS_SINK and + OMP_CLAUSE_DOACROSS_SOURCE instead of OMP_CLAUSE_DEPEND_SINK and + OMP_CLAUSE_DEPEND_SOURCE, build OMP_CLAUSE_DOACROSS for depend(source) + and set OMP_CLAUSE_DOACROSS_DEPEND on it. + (cp_parser_omp_clause_doacross): New function. + (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_DOACROSS. + (cp_parser_omp_depobj): Use OMP_CLAUSE_DEPEND_INVALID instead of + OMP_CLAUSE_DEPEND_SOURCE. + (cp_parser_omp_for_loop): Don't diagnose here linear clause together + with ordered with argument. + (cp_parser_omp_simd): Don't diagnose ordered clause with argument on + for simd. + (OMP_ORDERED_DEPEND_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DOACROSS. + (cp_parser_omp_ordered): Handle also doacross and adjust for it + diagnostic wording. + * pt.cc (tsubst_omp_clause_decl): Use + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of + OMP_CLAUSE_DEPEND_SINK_NEGATIVE. + (tsubst_omp_clauses): Handle OMP_CLAUSE_DOACROSS. + (tsubst_expr): Use OMP_CLAUSE_DEPEND_INVALID instead of + OMP_CLAUSE_DEPEND_SOURCE. + * semantics.cc (cp_finish_omp_clause_depend_sink): Rename to ... + (cp_finish_omp_clause_doacross_sink): ... this. + (finish_omp_clauses): Handle OMP_CLAUSE_DOACROSS. Don't handle + OMP_CLAUSE_DEPEND_SOURCE and OMP_CLAUSE_DEPEND_SINK. + +2022-09-02 David Malcolm <dmalcolm@redhat.com> + + PR c/90885 + * cp-tree.h (class cp_expr): Add bitfield m_decimal. Clear it in + existing ctors. Add ctor that allows specifying its value. + (cp_expr::decimal_p): New accessor. + * parser.cc (cp_parser_expression_stack_entry::flags): New field. + (cp_parser_primary_expression): Set m_decimal of cp_expr when + handling numbers. + (cp_parser_binary_expression): Extract flags from token when + populating stack. Call check_for_xor_used_as_pow. + +2022-09-01 Marek Polacek <polacek@redhat.com> + + * cp-tree.h (maybe_strip_ref_conversion): Remove. + +2022-08-30 Ulrich Drepper <drepper@gmail.com> + + * Make-lang.in: Add rule to rebuild std-name-hint.h from + std-name-hint.gperf. + * name-lookup.cc (get_std_name_hint): Remove hints array. + Use gperf-generated class std_name_hint_lookup. + Include "std-name-hint.h". + * std-name-hint.gperf: New file. + * std-name-hint.h: New file. Generated from the .gperf file. + +2022-08-30 Marek Polacek <polacek@redhat.com> + + PR c++/106759 + * cp-objcp-common.cc (names_builtin_p): Handle RID_IS_NOTHROW_ASSIGNABLE + and RID_IS_NOTHROW_CONSTRUCTIBLE. + +2022-08-29 Marek Polacek <polacek@redhat.com> + + PR c++/106712 + * decl.cc (grokdeclarator): Reverse the order of arguments to + attr_chainon. + +2022-08-26 Marek Polacek <polacek@redhat.com> + + PR c++/81159 + * typeck.cc (maybe_warn_self_move): New. + (cp_build_modify_expr): Call maybe_warn_self_move. + +2022-08-25 Marek Polacek <polacek@redhat.com> + + * cp-tree.h (enum cp_tree_index): Remove CTI_NULLPTR, CTI_NULLPTR_TYPE. + Move it to c_tree_index. + (nullptr_node): No longer define here. + (nullptr_type_node): Likewise. + (NULLPTR_TYPE_P): Likewise. + * decl.cc (cxx_init_decl_processing): Only keep C++-specific nullptr + initialization; move the shared code to c_common_nodes_and_builtins. + +2022-08-25 Jason Merrill <jason@redhat.com> + + * call.cc (unsafe_return_slot_p): Return 2 for *this in a + constructor. + 2022-08-23 Marek Polacek <polacek@redhat.com> * typeck.cc (maybe_warn_pessimizing_move): Don't warn about diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 23d98c8..38d8eee 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -153,6 +153,15 @@ endif gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -L C++ \ $(srcdir)/cp/cfns.gperf --output-file $(srcdir)/cp/cfns.h +# The same procedure for the std-name-hint.gperf file. +ifeq ($(ENABLE_MAINTAINER_RULES), true) +$(srcdir)/cp/std-name-hint.h: $(srcdir)/cp/std-name-hint.gperf +else +$(srcdir)/cp/std-name-hint.h: +endif + gperf -o -C -E -k '1,2,7,11,$$' -D -N find -L C++ \ + $(srcdir)/cp/std-name-hint.gperf --output-file $(srcdir)/cp/std-name-hint.h + cc1plus.fda: ../stage1-gcc/cc1plus$(exeext) ../prev-gcc/$(PERF_DATA) $(CREATE_GCOV) -binary ../stage1-gcc/cc1plus$(exeext) -gcov cc1plus.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 370137e..d107a28 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -9022,6 +9022,13 @@ unsafe_return_slot_p (tree t) if (is_empty_base_ref (t)) return 2; + /* A delegating constructor might be used to initialize a base. */ + if (current_function_decl + && DECL_CONSTRUCTOR_P (current_function_decl) + && (t == current_class_ref + || tree_strip_nop_conversions (t) == current_class_ptr)) + return 2; + STRIP_NOPS (t); if (TREE_CODE (t) == ADDR_EXPR) t = TREE_OPERAND (t, 0); diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc index 4079a4b..1ffac08 100644 --- a/gcc/cp/cp-objcp-common.cc +++ b/gcc/cp/cp-objcp-common.cc @@ -460,6 +460,8 @@ names_builtin_p (const char *name) case RID_IS_UNION: case RID_IS_ASSIGNABLE: case RID_IS_CONSTRUCTIBLE: + case RID_IS_NOTHROW_ASSIGNABLE: + case RID_IS_NOTHROW_CONSTRUCTIBLE: case RID_UNDERLYING_TYPE: case RID_REF_CONSTRUCTS_FROM_TEMPORARY: case RID_REF_CONVERTS_FROM_TEMPORARY: diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9f2ff37..7b28405 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -54,13 +54,23 @@ class cp_expr { public: cp_expr () : - m_value (NULL), m_loc (UNKNOWN_LOCATION) {} + m_value (NULL), m_loc (UNKNOWN_LOCATION), + m_decimal (false) + {} cp_expr (tree value) : - m_value (value), m_loc (cp_expr_location (m_value)) {} + m_value (value), m_loc (cp_expr_location (m_value)), + m_decimal (false) + {} cp_expr (tree value, location_t loc): - m_value (value), m_loc (loc) + m_value (value), m_loc (loc), m_decimal (false) + { + protected_set_expr_location (value, loc); + } + + cp_expr (tree value, location_t loc, bool decimal): + m_value (value), m_loc (loc), m_decimal (decimal) { protected_set_expr_location (value, loc); } @@ -102,9 +112,12 @@ public: return *this; } + bool decimal_p () const { return m_decimal; } + private: tree m_value; location_t m_loc; + bool m_decimal : 1; }; inline bool @@ -187,9 +200,6 @@ enum cp_tree_index CPTI_NOEXCEPT_FALSE_SPEC, CPTI_NOEXCEPT_DEFERRED_SPEC, - CPTI_NULLPTR, - CPTI_NULLPTR_TYPE, - CPTI_ANY_TARG, CPTI_MODULE_HWM, @@ -254,8 +264,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #define conv_op_marker cp_global_trees[CPTI_CONV_OP_MARKER] #define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL] #define current_aggr cp_global_trees[CPTI_AGGR_TAG] -#define nullptr_node cp_global_trees[CPTI_NULLPTR] -#define nullptr_type_node cp_global_trees[CPTI_NULLPTR_TYPE] /* std::align_val_t */ #define align_type_node cp_global_trees[CPTI_ALIGN_TYPE] @@ -4405,9 +4413,6 @@ get_vec_init_expr (tree t) || TREE_CODE (TYPE) == REAL_TYPE \ || TREE_CODE (TYPE) == COMPLEX_TYPE) -/* True iff TYPE is cv decltype(nullptr). */ -#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE) - /* [basic.types] Arithmetic types, enumeration types, pointer types, @@ -7606,7 +7611,6 @@ extern tree force_paren_expr (tree, bool = false); inline tree force_paren_expr_uneval (tree t) { return force_paren_expr (t, true); } extern tree maybe_undo_parenthesized_ref (tree); -extern tree maybe_strip_ref_conversion (tree); extern tree finish_non_static_data_member (tree, tree, tree, tsubst_flags_t = tf_warning_or_error); extern tree begin_stmt_expr (void); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 84a1a01..b72b2a8 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -4793,16 +4793,10 @@ cxx_init_decl_processing (void) } } - nullptr_type_node = make_node (NULLPTR_TYPE); - TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode)); - TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode)); - TYPE_UNSIGNED (nullptr_type_node) = 1; - TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode); + /* C++-specific nullptr initialization. */ if (abi_version_at_least (9)) SET_TYPE_ALIGN (nullptr_type_node, GET_MODE_ALIGNMENT (ptr_mode)); - SET_TYPE_MODE (nullptr_type_node, ptr_mode); record_builtin_type (RID_MAX, "decltype(nullptr)", nullptr_type_node); - nullptr_node = build_int_cst (nullptr_type_node, 0); } if (! supports_one_only ()) @@ -13480,7 +13474,7 @@ grokdeclarator (const cp_declarator *declarator, /* [dcl.meaning]/1: The optional attribute-specifier-seq following a declarator-id appertains to the entity that is declared. */ if (declarator->std_attributes != error_mark_node) - *attrlist = attr_chainon (*attrlist, declarator->std_attributes); + *attrlist = attr_chainon (declarator->std_attributes, *attrlist); else /* We should have already diagnosed the issue (c++/78344). */ gcc_assert (seen_error ()); diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index ce62276..f89a1dc 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -6691,20 +6691,14 @@ suggest_alternatives_in_other_namespaces (location_t location, tree name) } /* A well-known name within the C++ standard library, returned by - get_std_name_hint. */ + get_std_name_hint. -struct std_name_hint -{ - /* A name within "std::". */ - const char *name; - - /* The header name defining it within the C++ Standard Library - (with '<' and '>'). */ - const char *header; + The gperf-generated file contains the definition of the class + "std_name_hint_lookup" with a static member function which + returns the pointer to a structure "std_name_hint" which + is also defined in that file. */ - /* The dialect of C++ in which this was added. */ - enum cxx_dialect min_dialect; -}; +#include "std-name-hint.h" /* Subroutine of maybe_suggest_missing_header for handling unrecognized names for some of the most common names within "std::". @@ -6713,218 +6707,7 @@ struct std_name_hint static const std_name_hint * get_std_name_hint (const char *name) { - static const std_name_hint hints[] = { - /* <any>. */ - {"any", "<any>", cxx17}, - {"any_cast", "<any>", cxx17}, - {"make_any", "<any>", cxx17}, - /* <array>. */ - {"array", "<array>", cxx11}, - {"to_array", "<array>", cxx20}, - /* <atomic>. */ - {"atomic", "<atomic>", cxx11}, - {"atomic_flag", "<atomic>", cxx11}, - {"atomic_ref", "<atomic>", cxx20}, - /* <bitset>. */ - {"bitset", "<bitset>", cxx11}, - /* <compare> */ - {"weak_equality", "<compare>", cxx20}, - {"strong_equality", "<compare>", cxx20}, - {"partial_ordering", "<compare>", cxx20}, - {"weak_ordering", "<compare>", cxx20}, - {"strong_ordering", "<compare>", cxx20}, - /* <complex>. */ - {"complex", "<complex>", cxx98}, - {"complex_literals", "<complex>", cxx14}, - /* <condition_variable>. */ - {"condition_variable", "<condition_variable>", cxx11}, - {"condition_variable_any", "<condition_variable>", cxx11}, - /* <cstddef>. */ - {"byte", "<cstddef>", cxx17}, - /* <deque>. */ - {"deque", "<deque>", cxx98}, - /* <forward_list>. */ - {"forward_list", "<forward_list>", cxx11}, - /* <fstream>. */ - {"basic_filebuf", "<fstream>", cxx98}, - {"basic_ifstream", "<fstream>", cxx98}, - {"basic_ofstream", "<fstream>", cxx98}, - {"basic_fstream", "<fstream>", cxx98}, - {"fstream", "<fstream>", cxx98}, - {"ifstream", "<fstream>", cxx98}, - {"ofstream", "<fstream>", cxx98}, - /* <functional>. */ - {"bind", "<functional>", cxx11}, - {"bind_front", "<functional>", cxx20}, - {"function", "<functional>", cxx11}, - {"hash", "<functional>", cxx11}, - {"invoke", "<functional>", cxx17}, - {"mem_fn", "<functional>", cxx11}, - {"not_fn", "<functional>", cxx17}, - {"reference_wrapper", "<functional>", cxx11}, - {"unwrap_reference", "<functional>", cxx20}, - {"unwrap_reference_t", "<functional>", cxx20}, - {"unwrap_ref_decay", "<functional>", cxx20}, - {"unwrap_ref_decay_t", "<functional>", cxx20}, - /* <future>. */ - {"async", "<future>", cxx11}, - {"future", "<future>", cxx11}, - {"packaged_task", "<future>", cxx11}, - {"promise", "<future>", cxx11}, - /* <iostream>. */ - {"cin", "<iostream>", cxx98}, - {"cout", "<iostream>", cxx98}, - {"cerr", "<iostream>", cxx98}, - {"clog", "<iostream>", cxx98}, - {"wcin", "<iostream>", cxx98}, - {"wcout", "<iostream>", cxx98}, - {"wclog", "<iostream>", cxx98}, - /* <istream>. */ - {"istream", "<istream>", cxx98}, - /* <iterator>. */ - {"advance", "<iterator>", cxx98}, - {"back_inserter", "<iterator>", cxx98}, - {"begin", "<iterator>", cxx11}, - {"distance", "<iterator>", cxx98}, - {"end", "<iterator>", cxx11}, - {"front_inserter", "<iterator>", cxx98}, - {"inserter", "<iterator>", cxx98}, - {"istream_iterator", "<iterator>", cxx98}, - {"istreambuf_iterator", "<iterator>", cxx98}, - {"iterator_traits", "<iterator>", cxx98}, - {"move_iterator", "<iterator>", cxx11}, - {"next", "<iterator>", cxx11}, - {"ostream_iterator", "<iterator>", cxx98}, - {"ostreambuf_iterator", "<iterator>", cxx98}, - {"prev", "<iterator>", cxx11}, - {"reverse_iterator", "<iterator>", cxx98}, - /* <ostream>. */ - {"ostream", "<ostream>", cxx98}, - /* <list>. */ - {"list", "<list>", cxx98}, - /* <map>. */ - {"map", "<map>", cxx98}, - {"multimap", "<map>", cxx98}, - /* <memory>. */ - {"allocate_shared", "<memory>", cxx11}, - {"allocator", "<memory>", cxx98}, - {"allocator_traits", "<memory>", cxx11}, - {"make_shared", "<memory>", cxx11}, - {"make_unique", "<memory>", cxx14}, - {"shared_ptr", "<memory>", cxx11}, - {"unique_ptr", "<memory>", cxx11}, - {"weak_ptr", "<memory>", cxx11}, - /* <memory_resource>. */ - {"pmr", "<memory_resource>", cxx17}, - /* <mutex>. */ - {"mutex", "<mutex>", cxx11}, - {"timed_mutex", "<mutex>", cxx11}, - {"recursive_mutex", "<mutex>", cxx11}, - {"recursive_timed_mutex", "<mutex>", cxx11}, - {"once_flag", "<mutex>", cxx11}, - {"call_once,", "<mutex>", cxx11}, - {"lock", "<mutex>", cxx11}, - {"scoped_lock", "<mutex>", cxx17}, - {"try_lock", "<mutex>", cxx11}, - {"lock_guard", "<mutex>", cxx11}, - {"unique_lock", "<mutex>", cxx11}, - /* <optional>. */ - {"optional", "<optional>", cxx17}, - {"make_optional", "<optional>", cxx17}, - /* <ostream>. */ - {"ostream", "<ostream>", cxx98}, - {"wostream", "<ostream>", cxx98}, - {"ends", "<ostream>", cxx98}, - {"flush", "<ostream>", cxx98}, - {"endl", "<ostream>", cxx98}, - /* <queue>. */ - {"queue", "<queue>", cxx98}, - {"priority_queue", "<queue>", cxx98}, - /* <set>. */ - {"set", "<set>", cxx98}, - {"multiset", "<set>", cxx98}, - /* <shared_mutex>. */ - {"shared_lock", "<shared_mutex>", cxx14}, - {"shared_mutex", "<shared_mutex>", cxx17}, - {"shared_timed_mutex", "<shared_mutex>", cxx14}, - /* <source_location>. */ - {"source_location", "<source_location>", cxx20}, - /* <sstream>. */ - {"basic_stringbuf", "<sstream>", cxx98}, - {"basic_istringstream", "<sstream>", cxx98}, - {"basic_ostringstream", "<sstream>", cxx98}, - {"basic_stringstream", "<sstream>", cxx98}, - {"istringstream", "<sstream>", cxx98}, - {"ostringstream", "<sstream>", cxx98}, - {"stringstream", "<sstream>", cxx98}, - /* <stack>. */ - {"stack", "<stack>", cxx98}, - /* <string>. */ - {"basic_string", "<string>", cxx98}, - {"string", "<string>", cxx98}, - {"wstring", "<string>", cxx98}, - {"u8string", "<string>", cxx20}, - {"u16string", "<string>", cxx11}, - {"u32string", "<string>", cxx11}, - /* <string_view>. */ - {"basic_string_view", "<string_view>", cxx17}, - {"string_view", "<string_view>", cxx17}, - /* <thread>. */ - {"thread", "<thread>", cxx11}, - {"this_thread", "<thread>", cxx11}, - /* <tuple>. */ - {"apply", "<tuple>", cxx17}, - {"forward_as_tuple", "<tuple>", cxx11}, - {"make_from_tuple", "<tuple>", cxx17}, - {"make_tuple", "<tuple>", cxx11}, - {"tie", "<tuple>", cxx11}, - {"tuple", "<tuple>", cxx11}, - {"tuple_cat", "<tuple>", cxx11}, - {"tuple_element", "<tuple>", cxx11}, - {"tuple_element_t", "<tuple>", cxx14}, - {"tuple_size", "<tuple>", cxx11}, - {"tuple_size_v", "<tuple>", cxx17}, - /* <type_traits>. */ - {"enable_if", "<type_traits>", cxx11}, - {"enable_if_t", "<type_traits>", cxx14}, - {"invoke_result", "<type_traits>", cxx17}, - {"invoke_result_t", "<type_traits>", cxx17}, - {"remove_cvref", "<type_traits>", cxx20}, - {"remove_cvref_t", "<type_traits>", cxx20}, - {"type_identity", "<type_traits>", cxx20}, - {"type_identity_t", "<type_traits>", cxx20}, - {"void_t", "<type_traits>", cxx17}, - {"conjunction", "<type_traits>", cxx17}, - {"conjunction_v", "<type_traits>", cxx17}, - {"disjunction", "<type_traits>", cxx17}, - {"disjunction_v", "<type_traits>", cxx17}, - {"negation", "<type_traits>", cxx17}, - {"negation_v", "<type_traits>", cxx17}, - /* <unordered_map>. */ - {"unordered_map", "<unordered_map>", cxx11}, - {"unordered_multimap", "<unordered_map>", cxx11}, - /* <unordered_set>. */ - {"unordered_set", "<unordered_set>", cxx11}, - {"unordered_multiset", "<unordered_set>", cxx11}, - /* <utility>. */ - {"declval", "<utility>", cxx11}, - {"forward", "<utility>", cxx11}, - {"make_pair", "<utility>", cxx98}, - {"move", "<utility>", cxx11}, - {"pair", "<utility>", cxx98}, - /* <variant>. */ - {"variant", "<variant>", cxx17}, - {"visit", "<variant>", cxx17}, - /* <vector>. */ - {"vector", "<vector>", cxx98}, - }; - const size_t num_hints = ARRAY_SIZE (hints); - for (size_t i = 0; i < num_hints; i++) - { - if (strcmp (name, hints[i].name) == 0) - return &hints[i]; - } - return NULL; + return std_name_hint_lookup::find(name, strlen(name)); } /* Describe DIALECT. */ diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 68fc78e..076ad62 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -2069,6 +2069,8 @@ struct cp_parser_expression_stack_entry enum cp_parser_prec prec; /* Location of the binary operation we are parsing. */ location_t loc; + /* Flags from the operator token. */ + unsigned char flags; }; /* The stack for storing partial expressions. We only need NUM_PREC_VALUES @@ -5614,7 +5616,7 @@ cp_parser_primary_expression (cp_parser *parser, if (!cast_p) cp_parser_non_integral_constant_expression (parser, NIC_FLOAT); } - return (cp_expr (token->u.value, token->location) + return (cp_expr (token->u.value, token->location, token->flags & DECIMAL_INT) .maybe_add_location_wrapper ()); case CPP_CHAR_USERDEF: @@ -10160,6 +10162,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, get_rhs: current.tree_type = binops_by_token[token->type].tree_type; current.loc = token->location; + current.flags = token->flags; /* We used the operator token. */ cp_lexer_consume_token (parser->lexer); @@ -10244,6 +10247,18 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, warn_logical_not_parentheses (current.loc, current.tree_type, current.lhs, maybe_constant_value (rhs)); + if (warn_xor_used_as_pow + && current.tree_type == BIT_XOR_EXPR + /* Don't warn for named "xor" (as opposed to '^'). */ + && !(current.flags & NAMED_OP) + && current.lhs.decimal_p () + && rhs.decimal_p ()) + check_for_xor_used_as_pow + (current.lhs.get_location (), + tree_strip_any_location_wrapper (current.lhs), + current.loc, + tree_strip_any_location_wrapper (rhs)); + overload = NULL; location_t combined_loc = make_location (current.loc, @@ -11979,14 +11994,18 @@ cp_parser_handle_statement_omp_attributes (cp_parser *parser, tree attrs) if (dir->id == PRAGMA_OMP_ORDERED) { /* ordered is C_OMP_DIR_CONSTRUCT only if it doesn't contain - depend clause. */ - if (directive[1] && strcmp (directive[1], "depend") == 0) + depend/doacross clause. */ + if (directive[1] + && (strcmp (directive[1], "depend") == 0 + || strcmp (directive[1], "doacross") == 0)) kind = C_OMP_DIR_STANDALONE; else if (first + 2 < last && first[1].type == CPP_COMMA && first[2].type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (first[2].u.value), - "depend") == 0) + && (strcmp (IDENTIFIER_POINTER (first[2].u.value), + "depend") == 0 + || strcmp (IDENTIFIER_POINTER (first[2].u.value), + "doacross") == 0)) kind = C_OMP_DIR_STANDALONE; } else if (dir->id == PRAGMA_OMP_ERROR) @@ -36587,6 +36606,8 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE; else if (!strcmp ("dist_schedule", p)) result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE; + else if (!strcmp ("doacross", p)) + result = PRAGMA_OMP_CLAUSE_DOACROSS; break; case 'e': if (!strcmp ("enter", p)) @@ -39314,8 +39335,8 @@ cp_parser_omp_clause_simdlen (cp_parser *parser, tree list, */ static tree -cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, - tree list) +cp_parser_omp_clause_doacross_sink (cp_parser *parser, location_t clause_loc, + tree list, bool depend_p) { tree vec = NULL; @@ -39325,6 +39346,29 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, return list; } + if (!depend_p) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + if (strcmp (IDENTIFIER_POINTER (id), "omp_cur_iteration") == 0 + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_MINUS) + && cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) + && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)) + { + tree val = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value; + if (integer_onep (val) + && same_type_p (TREE_TYPE (val), integer_type_node)) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_CHAIN (u) = list; + return u; + } + } + } + while (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { location_t id_loc = cp_lexer_peek_token (parser->lexer)->location; @@ -39372,7 +39416,7 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, { vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) @@ -39384,8 +39428,9 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc, if (vec) { - tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK; + tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (u) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (u) = depend_p; OMP_CLAUSE_DECL (u) = nreverse (vec); OMP_CLAUSE_CHAIN (u) = list; return u; @@ -39634,6 +39679,7 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) { tree nlist, c, iterators = NULL_TREE; enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST; + enum omp_clause_doacross_kind dkind = OMP_CLAUSE_DOACROSS_LAST; matching_parens parens; if (!parens.require_open (parser)) @@ -39667,9 +39713,9 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) else if (strcmp ("depobj", p) == 0) kind = OMP_CLAUSE_DEPEND_DEPOBJ; else if (strcmp ("sink", p) == 0) - kind = OMP_CLAUSE_DEPEND_SINK; + dkind = OMP_CLAUSE_DOACROSS_SINK; else if (strcmp ("source", p) == 0) - kind = OMP_CLAUSE_DEPEND_SOURCE; + dkind = OMP_CLAUSE_DOACROSS_SOURCE; else goto invalid_kind; break; @@ -39679,18 +39725,20 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) cp_lexer_consume_token (parser->lexer); if (iterators - && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK)) + && (dkind == OMP_CLAUSE_DOACROSS_SOURCE + || dkind == OMP_CLAUSE_DOACROSS_SINK)) { poplevel (0, 1, 0); error_at (loc, "%<iterator%> modifier incompatible with %qs", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + dkind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); iterators = NULL_TREE; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (dkind == OMP_CLAUSE_DOACROSS_SOURCE) { - c = build_omp_clause (loc, OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = kind; + c = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = dkind; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; OMP_CLAUSE_DECL (c) = NULL_TREE; OMP_CLAUSE_CHAIN (c) = list; if (!parens.require_close (parser)) @@ -39703,9 +39751,9 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) goto resync_fail; - if (kind == OMP_CLAUSE_DEPEND_SINK) + if (dkind == OMP_CLAUSE_DOACROSS_SINK) { - nlist = cp_parser_omp_clause_depend_sink (parser, loc, list); + nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, true); if (!parens.require_close (parser)) cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -39746,6 +39794,73 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc) return list; } +/* OpenMP 5.2: + doacross ( source : ) + doacross ( source : omp_cur_iteration ) + + doacross ( sink : vec ) + doacross ( sink : omp_cur_iteration - logical_iteration ) */ + +static tree +cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc) +{ + tree nlist; + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_LAST; + + matching_parens parens; + if (!parens.require_open (parser)) + return list; + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + { + invalid_kind: + cp_parser_error (parser, "invalid doacross kind"); + resync_fail: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (strcmp ("sink", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SINK; + else if (strcmp ("source", p) == 0) + kind = OMP_CLAUSE_DOACROSS_SOURCE; + else + goto invalid_kind; + + cp_lexer_consume_token (parser->lexer); + + if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) + goto resync_fail; + + if (kind == OMP_CLAUSE_DOACROSS_SOURCE) + { + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + id = cp_lexer_peek_token (parser->lexer)->u.value; + p = IDENTIFIER_POINTER (id); + if (strcmp (p, "omp_cur_iteration") == 0) + cp_lexer_consume_token (parser->lexer); + } + nlist = build_omp_clause (loc, OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (nlist) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DECL (nlist) = NULL_TREE; + OMP_CLAUSE_CHAIN (nlist) = list; + } + else + nlist = cp_parser_omp_clause_doacross_sink (parser, loc, list, false); + + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return nlist; +} + /* OpenMP 4.0: map ( map-kind : variable-list ) map ( variable-list ) @@ -40688,6 +40803,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, token->location); c_name = "depend"; break; + case PRAGMA_OMP_CLAUSE_DOACROSS: + clauses = cp_parser_omp_clause_doacross (parser, clauses, + token->location); + c_name = "doacross"; + break; case PRAGMA_OMP_CLAUSE_DETACH: clauses = cp_parser_omp_clause_detach (parser, clauses); c_name = "detach"; @@ -41926,7 +42046,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) /*consume_paren=*/true); tree clause = NULL_TREE; - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; location_t c_loc = cp_lexer_peek_token (parser->lexer)->location; /* For now only in C++ attributes, do it always for OpenMP 5.1. */ if (parser->lexer->in_omp_attribute_pragma @@ -41974,7 +42094,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) else if (!strcmp ("inoutset", p2)) kind = OMP_CLAUSE_DEPEND_INOUTSET; } - if (kind == OMP_CLAUSE_DEPEND_SOURCE) + if (kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, " @@ -41990,7 +42110,7 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) clause = error_mark_node; } } - if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE) + if (!clause && kind == OMP_CLAUSE_DEPEND_INVALID) { clause = error_mark_node; error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause"); @@ -42822,19 +42942,6 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, = build_int_cst (NULL_TREE, collapse); ordered = collapse; } - if (ordered) - { - for (tree *pc = &clauses; *pc; ) - if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) - { - error_at (OMP_CLAUSE_LOCATION (*pc), - "%<linear%> clause may not be specified together " - "with %<ordered%> clause with a parameter"); - *pc = OMP_CLAUSE_CHAIN (*pc); - } - else - pc = &OMP_CLAUSE_CHAIN (*pc); - } gcc_assert (tiling || (collapse >= 1 && ordered >= 0)); count = ordered ? ordered : collapse; @@ -43286,15 +43393,6 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok, { cp_omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses); clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; - tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR], - OMP_CLAUSE_ORDERED); - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> clause with parameter may not be specified " - "on %qs construct", p_name); - OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE; - } } keep_next_level (true); @@ -43556,7 +43654,8 @@ cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD)) #define OMP_ORDERED_DEPEND_CLAUSE_MASK \ - (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DOACROSS)) static bool cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, @@ -43575,7 +43674,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, tree id = cp_lexer_peek_nth_token (parser->lexer, n)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (strcmp (p, "depend") == 0) + if (strcmp (p, "depend") == 0 || strcmp (p, "doacross") == 0) { if (!flag_openmp) /* flag_openmp_simd */ { @@ -43585,8 +43684,8 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok, if (context == pragma_stmt) { error_at (pragma_tok->location, "%<#pragma omp ordered%> with " - "%<depend%> clause may only be used in compound " - "statements"); + "%qs clause may only be used in compound " + "statements", p); cp_parser_skip_to_pragma_eol (parser, pragma_tok); return true; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fe7e809..cd0d892 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17830,8 +17830,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, } /* Handle an OpenMP array section represented as a TREE_LIST (or - OMP_CLAUSE_DEPEND_KIND). An OMP_CLAUSE_DEPEND (with a depend - kind of OMP_CLAUSE_DEPEND_SINK) can also be represented as a + OMP_CLAUSE_DOACROSS_KIND). An OMP_CLAUSE_DOACROSS (with a depend + kind of OMP_CLAUSE_DOACROSS_SINK) can also be represented as a TREE_LIST. We can handle it exactly the same as an array section (purpose, value, and a chain), even though the nomenclature (low_bound, length, etc) is different. */ @@ -17849,8 +17849,8 @@ tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain, && TREE_CHAIN (decl) == chain) return decl; tree ret = tree_cons (low_bound, length, chain); - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (ret) - = OMP_CLAUSE_DEPEND_SINK_NEGATIVE (decl); + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (ret) + = OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (decl); return ret; } tree ret = tsubst_expr (decl, args, complain, in_decl, @@ -17898,6 +17898,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_UNIFORM: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_AFFINITY: case OMP_CLAUSE_FROM: case OMP_CLAUSE_TO: @@ -19414,7 +19415,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, r = RECUR (OMP_DEPOBJ_DEPOBJ (t)); if (OMP_DEPOBJ_CLAUSES (t) && OMP_DEPOBJ_CLAUSES (t) != error_mark_node) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE; + enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INVALID; if (TREE_CODE (OMP_DEPOBJ_CLAUSES (t)) == OMP_CLAUSE) { tmp = tsubst_omp_clauses (OMP_DEPOBJ_CLAUSES (t), C_ORT_OMP, @@ -19432,7 +19433,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, } else finish_omp_depobj (EXPR_LOCATION (t), r, - OMP_CLAUSE_DEPEND_SOURCE, + OMP_CLAUSE_DEPEND_INVALID, OMP_DEPOBJ_CLAUSES (t)); break; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index ae7c8ea..7b2c495 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -6477,13 +6477,13 @@ finish_omp_declare_simd_methods (tree t) } } -/* Adjust sink depend clause to take into account pointer offsets. +/* Adjust sink depend/doacross clause to take into account pointer offsets. Return TRUE if there was a problem processing the offset, and the whole clause should be removed. */ static bool -cp_finish_omp_clause_depend_sink (tree sink_clause) +cp_finish_omp_clause_doacross_sink (tree sink_clause) { tree t = OMP_CLAUSE_DECL (sink_clause); gcc_assert (TREE_CODE (t) == TREE_LIST); @@ -7795,21 +7795,18 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } goto handle_field_decl; - case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: t = OMP_CLAUSE_DECL (c); if (t == NULL_TREE) + break; + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { - gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_SOURCE); - break; - } - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) - { - if (cp_finish_omp_clause_depend_sink (c)) + if (cp_finish_omp_clause_doacross_sink (c)) remove = true; break; } - /* FALLTHRU */ + gcc_unreachable (); + case OMP_CLAUSE_DEPEND: case OMP_CLAUSE_AFFINITY: t = OMP_CLAUSE_DECL (c); if (TREE_CODE (t) == TREE_LIST diff --git a/gcc/cp/std-name-hint.gperf b/gcc/cp/std-name-hint.gperf new file mode 100644 index 0000000..976b90c --- /dev/null +++ b/gcc/cp/std-name-hint.gperf @@ -0,0 +1,287 @@ +%language=C++ +%define class-name std_name_hint_lookup +%struct-type +%{ +/* Copyright (C) 2022 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ +%} +struct std_name_hint +{ + /* A name within "std::". */ + const char *name; + + /* The header name defining it within the C++ Standard Library + (with '<' and '>'). */ + const char* header; + + /* The dialect of C++ in which this was added. */ + enum cxx_dialect min_dialect; +}; +%% +# The standard-defined types, functions, and options in the std:: namespace +# as defined in the C++ language specification. The result is used in the +# get_std_name_hint functions. +# throws an exception. +# +# <any> +any, "<any>", cxx17 +any_cast, "<any>", cxx17 +make_any, "<any>", cxx17 +# <array> +array, "<array>", cxx11 +to_array, "<array>", cxx20 +# <atomic> +atomic, "<atomic>", cxx11 +atomic_flag, "<atomic>", cxx11 +atomic_ref, "<atomic>", cxx20 +# <bitset> +bitset, "<bitset>", cxx11 +# <compare> +weak_equality, "<compare>", cxx20 +strong_equality, "<compare>", cxx20 +partial_ordering, "<compare>", cxx20 +weak_ordering, "<compare>", cxx20 +strong_ordering, "<compare>", cxx20 +# <complex> +complex, "<complex>", cxx98 +complex_literals, "<complex>", cxx14 +# <condition_variable>. */ +condition_variable, "<condition_variable>", cxx11 +condition_variable_any, "<condition_variable>", cxx11 +# <cstddef> +byte, "<cstddef>", cxx17 +# <deque> +deque, "<deque>", cxx98 +# <forward_list> +forward_list, "<forward_list>", cxx11 +# <fstream> +basic_filebuf, "<fstream>", cxx98 +basic_ifstream, "<fstream>", cxx98 +basic_ofstream, "<fstream>", cxx98 +basic_fstream, "<fstream>", cxx98 +fstream, "<fstream>", cxx98 +ifstream, "<fstream>", cxx98 +ofstream, "<fstream>", cxx98 +# <functional> +bind, "<functional>", cxx11 +bind_front, "<functional>", cxx20 +function, "<functional>", cxx11 +hash, "<functional>", cxx11 +invoke, "<functional>", cxx17 +mem_fn, "<functional>", cxx11 +not_fn, "<functional>", cxx17 +reference_wrapper, "<functional>", cxx11 +unwrap_reference, "<functional>", cxx20 +unwrap_reference_t, "<functional>", cxx20 +unwrap_ref_decay, "<functional>", cxx20 +unwrap_ref_decay_t, "<functional>", cxx20 +# <future>. */ +async, "<future>", cxx11 +future, "<future>", cxx11 +packaged_task, "<future>", cxx11 +promise, "<future>", cxx11 +# <iomanip> +resetiosflags, "<iomanip>", cxx98 +setiosflags, "<iomanip>", cxx98 +setbase, "<iomanip>", cxx98 +setfill, "<iomanip>", cxx98 +setprecision, "<iomanip>", cxx98 +setw, "<iomanip>", cxx98 +get_money, "<iomanip>", cxx11 +put_money, "<iomanip>", cxx11 +get_time, "<iomanip>", cxx11 +put_time, "<iomanip>", cxx11 +quoted, "<iomanip>", cxx14 +# <ios> +boolalpha, "<ios>", cxx98 +noboolalpha, "<ios>", cxx98 +showbase, "<ios>", cxx98 +noshowbase, "<ios>", cxx98 +showpoint, "<ios>", cxx98 +noshowpoint, "<ios>", cxx98 +showpos, "<ios>", cxx98 +noshowpos, "<ios>", cxx98 +skipws, "<ios>", cxx98 +noskipws, "<ios>", cxx98 +uppercase, "<ios>", cxx98 +nouppercase, "<ios>", cxx98 +unitbuf, "<ios>", cxx98 +nounitbuf, "<ios>", cxx98 +internal, "<ios>", cxx98 +left, "<ios>", cxx98 +right, "<ios>", cxx98 +dec, "<ios>", cxx98 +hex, "<ios>", cxx98 +oct, "<ios>", cxx98 +fixed, "<ios>", cxx98 +scientific, "<ios>", cxx98 +hexfloat, "<ios>", cxx11 +defaultfloat, "<ios>", cxx11 +# <iostream> +cin, "<iostream>", cxx98 +cout, "<iostream>", cxx98 +cerr, "<iostream>", cxx98 +clog, "<iostream>", cxx98 +wcin, "<iostream>", cxx98 +wcout, "<iostream>", cxx98 +wclog, "<iostream>", cxx98 +# <istream> +istream, "<istream>", cxx98 +ws, "<istream>", cxx98 +# <iterator> +advance, "<iterator>", cxx98 +back_inserter, "<iterator>", cxx98 +begin, "<iterator>", cxx11 +distance, "<iterator>", cxx98 +end, "<iterator>", cxx11 +front_inserter, "<iterator>", cxx98 +inserter, "<iterator>", cxx98 +istream_iterator, "<iterator>", cxx98 +istreambuf_iterator, "<iterator>", cxx98 +iterator_traits, "<iterator>", cxx98 +move_iterator, "<iterator>", cxx11 +next, "<iterator>", cxx11 +ostream_iterator, "<iterator>", cxx98 +ostreambuf_iterator, "<iterator>", cxx98 +prev, "<iterator>", cxx11 +reverse_iterator, "<iterator>", cxx98 +# <ostream> +ostream, "<ostream>", cxx98 +ends, "<ostream>", cxx98 +flush, "<ostream>", cxx98 +endl, "<ostream>", cxx98 +emit_on_flush, "<ostream>", cxx20 +noemit_on_flush, "<ostream>", cxx20 +flush_emit, "<ostream>", cxx20 +# <list> +list, "<list>", cxx98 +# <map> +map, "<map>", cxx98 +multimap, "<map>", cxx98 +# <memory> +allocate_shared, "<memory>", cxx11 +allocator, "<memory>", cxx98 +allocator_traits, "<memory>", cxx11 +make_shared, "<memory>", cxx11 +make_unique, "<memory>", cxx14 +shared_ptr, "<memory>", cxx11 +unique_ptr, "<memory>", cxx11 +weak_ptr, "<memory>", cxx11 +# <memory_resource> +pmr, "<memory_resource>", cxx17 +# <mutex> +mutex, "<mutex>", cxx11 +timed_mutex, "<mutex>", cxx11 +recursive_mutex, "<mutex>", cxx11 +recursive_timed_mutex, "<mutex>", cxx11 +once_flag, "<mutex>", cxx11 +call_once, "<mutex>", cxx11 +lock, "<mutex>", cxx11 +scoped_lock, "<mutex>", cxx17 +try_lock, "<mutex>", cxx11 +lock_guard, "<mutex>", cxx11 +unique_lock, "<mutex>", cxx11 +# <optional>. */ +optional, "<optional>", cxx17 +make_optional, "<optional>", cxx17 +# <ostream> +ostream, "<ostream>", cxx98 +wostream, "<ostream>", cxx98 +ends, "<ostream>", cxx98 +flush, "<ostream>", cxx98 +endl, "<ostream>", cxx98 +# <queue> +queue, "<queue>", cxx98 +priority_queue, "<queue>", cxx98 +# <set> +set, "<set>", cxx98 +multiset, "<set>", cxx98 +# <shared_mutex> +shared_lock, "<shared_mutex>", cxx14 +shared_mutex, "<shared_mutex>", cxx17 +shared_timed_mutex, "<shared_mutex>", cxx14 +# <source_location> +source_location, "<source_location>", cxx20 +# <sstream> +basic_stringbuf, "<sstream>", cxx98 +basic_istringstream, "<sstream>", cxx98 +basic_ostringstream, "<sstream>", cxx98 +basic_stringstream, "<sstream>", cxx98 +istringstream, "<sstream>", cxx98 +ostringstream, "<sstream>", cxx98 +stringstream, "<sstream>", cxx98 +# <stack> +stack, "<stack>", cxx98 +# <string> +basic_string, "<string>", cxx98 +string, "<string>", cxx98 +wstring, "<string>", cxx98 +u8string, "<string>", cxx20 +u16string, "<string>", cxx11 +u32string, "<string>", cxx11 +# <string_view> +basic_string_view, "<string_view>", cxx17 +string_view, "<string_view>", cxx17 +# <thread> +thread, "<thread>", cxx11 +this_thread, "<thread>", cxx11 +# <tuple> +apply, "<tuple>", cxx17 +forward_as_tuple, "<tuple>", cxx11 +make_from_tuple, "<tuple>", cxx17 +make_tuple, "<tuple>", cxx11 +tie, "<tuple>", cxx11 +tuple, "<tuple>", cxx11 +tuple_cat, "<tuple>", cxx11 +tuple_element, "<tuple>", cxx11 +tuple_element_t, "<tuple>", cxx14 +tuple_size, "<tuple>", cxx11 +tuple_size_v, "<tuple>", cxx17 +# <type_traits> +enable_if, "<type_traits>", cxx11 +enable_if_t, "<type_traits>", cxx14 +invoke_result, "<type_traits>", cxx17 +invoke_result_t, "<type_traits>", cxx17 +remove_cvref, "<type_traits>", cxx20 +remove_cvref_t, "<type_traits>", cxx20 +type_identity, "<type_traits>", cxx20 +type_identity_t, "<type_traits>", cxx20 +void_t, "<type_traits>", cxx17 +conjunction, "<type_traits>", cxx17 +conjunction_v, "<type_traits>", cxx17 +disjunction, "<type_traits>", cxx17 +disjunction_v, "<type_traits>", cxx17 +negation, "<type_traits>", cxx17 +negation_v, "<type_traits>", cxx17 +# <unordered_map> +unordered_map, "<unordered_map>", cxx11 +unordered_multimap, "<unordered_map>", cxx11 +# <unordered_set> +unordered_set, "<unordered_set>", cxx11 +unordered_multiset, "<unordered_set>", cxx11 +# <utility> +declval, "<utility>", cxx11 +forward, "<utility>", cxx11 +make_pair, "<utility>", cxx98 +move, "<utility>", cxx11 +pair, "<utility>", cxx98 +# <variant> +variant, "<variant>", cxx17 +visit, "<variant>", cxx17 +# <vector> +vector, "<vector>", cxx98 diff --git a/gcc/cp/std-name-hint.h b/gcc/cp/std-name-hint.h new file mode 100644 index 0000000..c48eac3 --- /dev/null +++ b/gcc/cp/std-name-hint.h @@ -0,0 +1,675 @@ +/* C++ code produced by gperf version 3.1 */ +/* Command-line: gperf -o -C -E -D -N find -L C++ --output-file std-name-hint.h -k'1,2,7,11,$' std-name-hint.gperf */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." +#endif + +#line 4 "std-name-hint.gperf" + +/* Copyright (C) 2022 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ +#line 23 "std-name-hint.gperf" +struct std_name_hint +{ + /* A name within "std::". */ + const char *name; + + /* The header name defining it within the C++ Standard Library + (with '<' and '>'). */ + const char* header; + + /* The dialect of C++ in which this was added. */ + enum cxx_dialect min_dialect; +}; +/* maximum key range = 626, duplicates = 4 */ + +class std_name_hint_lookup +{ +private: + static inline unsigned int hash (const char *str, size_t len); +public: + static const struct std_name_hint *find (const char *str, size_t len); +}; + +inline unsigned int +std_name_hint_lookup::hash (const char *str, size_t len) +{ + static const unsigned short asso_values[] = + { + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 5, + 635, 0, 635, 635, 635, 635, 25, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 45, 635, 25, 70, 165, + 20, 0, 35, 225, 190, 95, 635, 120, 183, 10, + 5, 25, 165, 5, 5, 10, 0, 55, 4, 143, + 115, 229, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635, 635, 635, 635, 635, + 635, 635, 635, 635, 635, 635 + }; + unsigned int hval = len; + + switch (hval) + { + default: + hval += asso_values[static_cast<unsigned char>(str[10])]; + /*FALLTHROUGH*/ + case 10: + case 9: + case 8: + case 7: + hval += asso_values[static_cast<unsigned char>(str[6])]; + /*FALLTHROUGH*/ + case 6: + case 5: + case 4: + case 3: + case 2: + hval += asso_values[static_cast<unsigned char>(str[1])]; + /*FALLTHROUGH*/ + case 1: + hval += asso_values[static_cast<unsigned char>(str[0])]; + break; + } + return hval + asso_values[static_cast<unsigned char>(str[len - 1])]; +} + +const struct std_name_hint * +std_name_hint_lookup::find (const char *str, size_t len) +{ + enum + { + TOTAL_KEYWORDS = 205, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 22, + MIN_HASH_VALUE = 9, + MAX_HASH_VALUE = 634 + }; + + static const struct std_name_hint wordlist[] = + { +#line 158 "std-name-hint.gperf" + {"next", "<iterator>", cxx11}, +#line 212 "std-name-hint.gperf" + {"set", "<set>", cxx98}, +#line 287 "std-name-hint.gperf" + {"vector", "<vector>", cxx98}, +#line 101 "std-name-hint.gperf" + {"setbase", "<iomanip>", cxx98}, +#line 165 "std-name-hint.gperf" + {"ends", "<ostream>", cxx98}, +#line 205 "std-name-hint.gperf" + {"ends", "<ostream>", cxx98}, +#line 86 "std-name-hint.gperf" + {"mem_fn", "<functional>", cxx11}, +#line 69 "std-name-hint.gperf" + {"deque", "<deque>", cxx98}, +#line 162 "std-name-hint.gperf" + {"reverse_iterator", "<iterator>", cxx98}, +#line 151 "std-name-hint.gperf" + {"end", "<iterator>", cxx11}, +#line 264 "std-name-hint.gperf" + {"void_t", "<type_traits>", cxx17}, +#line 284 "std-name-hint.gperf" + {"variant", "<variant>", cxx17}, +#line 281 "std-name-hint.gperf" + {"move", "<utility>", cxx11}, +#line 87 "std-name-hint.gperf" + {"not_fn", "<functional>", cxx17}, +#line 269 "std-name-hint.gperf" + {"negation", "<type_traits>", cxx17}, +#line 270 "std-name-hint.gperf" + {"negation_v", "<type_traits>", cxx17}, +#line 122 "std-name-hint.gperf" + {"nouppercase", "<ios>", cxx98}, +#line 43 "std-name-hint.gperf" + {"any_cast", "<any>", cxx17}, +#line 181 "std-name-hint.gperf" + {"make_unique", "<memory>", cxx14}, +#line 147 "std-name-hint.gperf" + {"advance", "<iterator>", cxx98}, +#line 157 "std-name-hint.gperf" + {"move_iterator", "<iterator>", cxx11}, +#line 246 "std-name-hint.gperf" + {"make_from_tuple", "<tuple>", cxx17}, +#line 134 "std-name-hint.gperf" + {"defaultfloat", "<ios>", cxx11}, +#line 249 "std-name-hint.gperf" + {"tuple", "<tuple>", cxx11}, +#line 257 "std-name-hint.gperf" + {"enable_if_t", "<type_traits>", cxx14}, +#line 164 "std-name-hint.gperf" + {"ostream", "<ostream>", cxx98}, +#line 203 "std-name-hint.gperf" + {"ostream", "<ostream>", cxx98}, +#line 261 "std-name-hint.gperf" + {"remove_cvref_t", "<type_traits>", cxx20}, +#line 209 "std-name-hint.gperf" + {"queue", "<queue>", cxx98}, +#line 159 "std-name-hint.gperf" + {"ostream_iterator", "<iterator>", cxx98}, +#line 227 "std-name-hint.gperf" + {"stringstream", "<sstream>", cxx98}, +#line 251 "std-name-hint.gperf" + {"tuple_element", "<tuple>", cxx11}, +#line 252 "std-name-hint.gperf" + {"tuple_element_t", "<tuple>", cxx14}, +#line 77 "std-name-hint.gperf" + {"fstream", "<fstream>", cxx98}, +#line 213 "std-name-hint.gperf" + {"multiset", "<set>", cxx98}, +#line 280 "std-name-hint.gperf" + {"make_pair", "<utility>", cxx98}, +#line 253 "std-name-hint.gperf" + {"tuple_size", "<tuple>", cxx11}, +#line 100 "std-name-hint.gperf" + {"setiosflags", "<iomanip>", cxx98}, +#line 99 "std-name-hint.gperf" + {"resetiosflags", "<iomanip>", cxx98}, +#line 149 "std-name-hint.gperf" + {"begin", "<iterator>", cxx11}, +#line 109 "std-name-hint.gperf" + {"quoted", "<iomanip>", cxx14}, +#line 275 "std-name-hint.gperf" + {"unordered_set", "<unordered_set>", cxx11}, +#line 276 "std-name-hint.gperf" + {"unordered_multiset", "<unordered_set>", cxx11}, +#line 256 "std-name-hint.gperf" + {"enable_if", "<type_traits>", cxx11}, +#line 95 "std-name-hint.gperf" + {"future", "<future>", cxx11}, +#line 260 "std-name-hint.gperf" + {"remove_cvref", "<type_traits>", cxx20}, +#line 248 "std-name-hint.gperf" + {"tie", "<tuple>", cxx11}, +#line 247 "std-name-hint.gperf" + {"make_tuple", "<tuple>", cxx11}, +#line 71 "std-name-hint.gperf" + {"forward_list", "<forward_list>", cxx11}, +#line 79 "std-name-hint.gperf" + {"ofstream", "<fstream>", cxx98}, +#line 285 "std-name-hint.gperf" + {"visit", "<variant>", cxx17}, +#line 127 "std-name-hint.gperf" + {"right", "<ios>", cxx98}, +#line 85 "std-name-hint.gperf" + {"invoke", "<functional>", cxx17}, +#line 279 "std-name-hint.gperf" + {"forward", "<utility>", cxx11}, +#line 114 "std-name-hint.gperf" + {"noshowbase", "<ios>", cxx98}, +#line 153 "std-name-hint.gperf" + {"inserter", "<iterator>", cxx98}, +#line 160 "std-name-hint.gperf" + {"ostreambuf_iterator", "<iterator>", cxx98}, +#line 51 "std-name-hint.gperf" + {"atomic_ref", "<atomic>", cxx20}, +#line 112 "std-name-hint.gperf" + {"noboolalpha", "<ios>", cxx98}, +#line 148 "std-name-hint.gperf" + {"back_inserter", "<iterator>", cxx98}, +#line 183 "std-name-hint.gperf" + {"unique_ptr", "<memory>", cxx11}, +#line 89 "std-name-hint.gperf" + {"unwrap_reference", "<functional>", cxx20}, +#line 90 "std-name-hint.gperf" + {"unwrap_reference_t", "<functional>", cxx20}, +#line 219 "std-name-hint.gperf" + {"source_location", "<source_location>", cxx20}, +#line 254 "std-name-hint.gperf" + {"tuple_size_v", "<tuple>", cxx17}, +#line 83 "std-name-hint.gperf" + {"function", "<functional>", cxx11}, +#line 144 "std-name-hint.gperf" + {"istream", "<istream>", cxx98}, +#line 229 "std-name-hint.gperf" + {"stack", "<stack>", cxx98}, +#line 154 "std-name-hint.gperf" + {"istream_iterator", "<iterator>", cxx98}, +#line 123 "std-name-hint.gperf" + {"unitbuf", "<ios>", cxx98}, +#line 224 "std-name-hint.gperf" + {"basic_stringstream", "<sstream>", cxx98}, +#line 245 "std-name-hint.gperf" + {"forward_as_tuple", "<tuple>", cxx11}, +#line 124 "std-name-hint.gperf" + {"nounitbuf", "<ios>", cxx98}, +#line 119 "std-name-hint.gperf" + {"skipws", "<ios>", cxx98}, +#line 75 "std-name-hint.gperf" + {"basic_ofstream", "<fstream>", cxx98}, +#line 156 "std-name-hint.gperf" + {"iterator_traits", "<iterator>", cxx98}, +#line 76 "std-name-hint.gperf" + {"basic_fstream", "<fstream>", cxx98}, +#line 131 "std-name-hint.gperf" + {"fixed", "<ios>", cxx98}, +#line 184 "std-name-hint.gperf" + {"weak_ptr", "<memory>", cxx11}, +#line 104 "std-name-hint.gperf" + {"setw", "<iomanip>", cxx98}, +#line 152 "std-name-hint.gperf" + {"front_inserter", "<iterator>", cxx98}, +#line 221 "std-name-hint.gperf" + {"basic_stringbuf", "<sstream>", cxx98}, +#line 145 "std-name-hint.gperf" + {"ws", "<istream>", cxx98}, +#line 92 "std-name-hint.gperf" + {"unwrap_ref_decay_t", "<functional>", cxx20}, +#line 53 "std-name-hint.gperf" + {"bitset", "<bitset>", cxx11}, +#line 78 "std-name-hint.gperf" + {"ifstream", "<fstream>", cxx98}, +#line 138 "std-name-hint.gperf" + {"cerr", "<iostream>", cxx98}, +#line 88 "std-name-hint.gperf" + {"reference_wrapper", "<functional>", cxx11}, +#line 97 "std-name-hint.gperf" + {"promise", "<future>", cxx11}, +#line 161 "std-name-hint.gperf" + {"prev", "<iterator>", cxx11}, +#line 82 "std-name-hint.gperf" + {"bind_front", "<functional>", cxx20}, +#line 186 "std-name-hint.gperf" + {"pmr", "<memory_resource>", cxx17}, +#line 155 "std-name-hint.gperf" + {"istreambuf_iterator", "<iterator>", cxx98}, +#line 188 "std-name-hint.gperf" + {"mutex", "<mutex>", cxx11}, +#line 126 "std-name-hint.gperf" + {"left", "<ios>", cxx98}, +#line 128 "std-name-hint.gperf" + {"dec", "<ios>", cxx98}, +#line 81 "std-name-hint.gperf" + {"bind", "<functional>", cxx11}, +#line 120 "std-name-hint.gperf" + {"noskipws", "<ios>", cxx98}, +#line 167 "std-name-hint.gperf" + {"endl", "<ostream>", cxx98}, +#line 207 "std-name-hint.gperf" + {"endl", "<ostream>", cxx98}, +#line 130 "std-name-hint.gperf" + {"oct", "<ios>", cxx98}, +#line 137 "std-name-hint.gperf" + {"cout", "<iostream>", cxx98}, +#line 49 "std-name-hint.gperf" + {"atomic", "<atomic>", cxx11}, +#line 282 "std-name-hint.gperf" + {"pair", "<utility>", cxx98}, +#line 174 "std-name-hint.gperf" + {"map", "<map>", cxx98}, +#line 193 "std-name-hint.gperf" + {"call_once", "<mutex>", cxx11}, +#line 94 "std-name-hint.gperf" + {"async", "<future>", cxx11}, +#line 116 "std-name-hint.gperf" + {"noshowpoint", "<ios>", cxx98}, +#line 204 "std-name-hint.gperf" + {"wostream", "<ostream>", cxx98}, +#line 258 "std-name-hint.gperf" + {"invoke_result", "<type_traits>", cxx17}, +#line 118 "std-name-hint.gperf" + {"noshowpos", "<ios>", cxx98}, +#line 259 "std-name-hint.gperf" + {"invoke_result_t", "<type_traits>", cxx17}, +#line 241 "std-name-hint.gperf" + {"thread", "<thread>", cxx11}, +#line 103 "std-name-hint.gperf" + {"setprecision", "<iomanip>", cxx98}, +#line 113 "std-name-hint.gperf" + {"showbase", "<ios>", cxx98}, +#line 74 "std-name-hint.gperf" + {"basic_ifstream", "<fstream>", cxx98}, +#line 178 "std-name-hint.gperf" + {"allocator", "<memory>", cxx98}, +#line 133 "std-name-hint.gperf" + {"hexfloat", "<ios>", cxx11}, +#line 117 "std-name-hint.gperf" + {"showpos", "<ios>", cxx98}, +#line 170 "std-name-hint.gperf" + {"flush_emit", "<ostream>", cxx20}, +#line 250 "std-name-hint.gperf" + {"tuple_cat", "<tuple>", cxx11}, +#line 179 "std-name-hint.gperf" + {"allocator_traits", "<memory>", cxx11}, +#line 191 "std-name-hint.gperf" + {"recursive_timed_mutex", "<mutex>", cxx11}, +#line 108 "std-name-hint.gperf" + {"put_time", "<iomanip>", cxx11}, +#line 210 "std-name-hint.gperf" + {"priority_queue", "<queue>", cxx98}, +#line 190 "std-name-hint.gperf" + {"recursive_mutex", "<mutex>", cxx11}, +#line 232 "std-name-hint.gperf" + {"string", "<string>", cxx98}, +#line 107 "std-name-hint.gperf" + {"get_time", "<iomanip>", cxx11}, +#line 223 "std-name-hint.gperf" + {"basic_ostringstream", "<sstream>", cxx98}, +#line 73 "std-name-hint.gperf" + {"basic_filebuf", "<fstream>", cxx98}, +#line 272 "std-name-hint.gperf" + {"unordered_map", "<unordered_map>", cxx11}, +#line 121 "std-name-hint.gperf" + {"uppercase", "<ios>", cxx98}, +#line 273 "std-name-hint.gperf" + {"unordered_multimap", "<unordered_map>", cxx11}, +#line 182 "std-name-hint.gperf" + {"shared_ptr", "<memory>", cxx11}, +#line 42 "std-name-hint.gperf" + {"any", "<any>", cxx17}, +#line 175 "std-name-hint.gperf" + {"multimap", "<map>", cxx98}, +#line 46 "std-name-hint.gperf" + {"array", "<array>", cxx11}, +#line 136 "std-name-hint.gperf" + {"cin", "<iostream>", cxx98}, +#line 238 "std-name-hint.gperf" + {"basic_string_view", "<string_view>", cxx17}, +#line 168 "std-name-hint.gperf" + {"emit_on_flush", "<ostream>", cxx20}, +#line 180 "std-name-hint.gperf" + {"make_shared", "<memory>", cxx11}, +#line 44 "std-name-hint.gperf" + {"make_any", "<any>", cxx17}, +#line 172 "std-name-hint.gperf" + {"list", "<list>", cxx98}, +#line 226 "std-name-hint.gperf" + {"ostringstream", "<sstream>", cxx98}, +#line 47 "std-name-hint.gperf" + {"to_array", "<array>", cxx20}, +#line 150 "std-name-hint.gperf" + {"distance", "<iterator>", cxx98}, +#line 197 "std-name-hint.gperf" + {"lock_guard", "<mutex>", cxx11}, +#line 111 "std-name-hint.gperf" + {"boolalpha", "<ios>", cxx98}, +#line 59 "std-name-hint.gperf" + {"strong_ordering", "<compare>", cxx20}, +#line 196 "std-name-hint.gperf" + {"try_lock", "<mutex>", cxx11}, +#line 267 "std-name-hint.gperf" + {"disjunction", "<type_traits>", cxx17}, +#line 268 "std-name-hint.gperf" + {"disjunction_v", "<type_traits>", cxx17}, +#line 67 "std-name-hint.gperf" + {"byte", "<cstddef>", cxx17}, +#line 115 "std-name-hint.gperf" + {"showpoint", "<ios>", cxx98}, +#line 64 "std-name-hint.gperf" + {"condition_variable", "<condition_variable>", cxx11}, +#line 129 "std-name-hint.gperf" + {"hex", "<ios>", cxx98}, +#line 141 "std-name-hint.gperf" + {"wcout", "<iostream>", cxx98}, +#line 222 "std-name-hint.gperf" + {"basic_istringstream", "<sstream>", cxx98}, +#line 169 "std-name-hint.gperf" + {"noemit_on_flush", "<ostream>", cxx20}, +#line 125 "std-name-hint.gperf" + {"internal", "<ios>", cxx98}, +#line 140 "std-name-hint.gperf" + {"wcin", "<iostream>", cxx98}, +#line 234 "std-name-hint.gperf" + {"u8string", "<string>", cxx20}, +#line 56 "std-name-hint.gperf" + {"strong_equality", "<compare>", cxx20}, +#line 62 "std-name-hint.gperf" + {"complex_literals", "<complex>", cxx14}, +#line 194 "std-name-hint.gperf" + {"lock", "<mutex>", cxx11}, +#line 189 "std-name-hint.gperf" + {"timed_mutex", "<mutex>", cxx11}, +#line 231 "std-name-hint.gperf" + {"basic_string", "<string>", cxx98}, +#line 96 "std-name-hint.gperf" + {"packaged_task", "<future>", cxx11}, +#line 239 "std-name-hint.gperf" + {"string_view", "<string_view>", cxx17}, +#line 225 "std-name-hint.gperf" + {"istringstream", "<sstream>", cxx98}, +#line 198 "std-name-hint.gperf" + {"unique_lock", "<mutex>", cxx11}, +#line 263 "std-name-hint.gperf" + {"type_identity_t", "<type_traits>", cxx20}, +#line 216 "std-name-hint.gperf" + {"shared_mutex", "<shared_mutex>", cxx17}, +#line 265 "std-name-hint.gperf" + {"conjunction", "<type_traits>", cxx17}, +#line 266 "std-name-hint.gperf" + {"conjunction_v", "<type_traits>", cxx17}, +#line 217 "std-name-hint.gperf" + {"shared_timed_mutex", "<shared_mutex>", cxx14}, +#line 102 "std-name-hint.gperf" + {"setfill", "<iomanip>", cxx98}, +#line 236 "std-name-hint.gperf" + {"u32string", "<string>", cxx11}, +#line 235 "std-name-hint.gperf" + {"u16string", "<string>", cxx11}, +#line 278 "std-name-hint.gperf" + {"declval", "<utility>", cxx11}, +#line 91 "std-name-hint.gperf" + {"unwrap_ref_decay", "<functional>", cxx20}, +#line 201 "std-name-hint.gperf" + {"make_optional", "<optional>", cxx17}, +#line 200 "std-name-hint.gperf" + {"optional", "<optional>", cxx17}, +#line 84 "std-name-hint.gperf" + {"hash", "<functional>", cxx11}, +#line 166 "std-name-hint.gperf" + {"flush", "<ostream>", cxx98}, +#line 206 "std-name-hint.gperf" + {"flush", "<ostream>", cxx98}, +#line 244 "std-name-hint.gperf" + {"apply", "<tuple>", cxx17}, +#line 61 "std-name-hint.gperf" + {"complex", "<complex>", cxx98}, +#line 242 "std-name-hint.gperf" + {"this_thread", "<thread>", cxx11}, +#line 177 "std-name-hint.gperf" + {"allocate_shared", "<memory>", cxx11}, +#line 132 "std-name-hint.gperf" + {"scientific", "<ios>", cxx98}, +#line 192 "std-name-hint.gperf" + {"once_flag", "<mutex>", cxx11}, +#line 106 "std-name-hint.gperf" + {"put_money", "<iomanip>", cxx11}, +#line 105 "std-name-hint.gperf" + {"get_money", "<iomanip>", cxx11}, +#line 195 "std-name-hint.gperf" + {"scoped_lock", "<mutex>", cxx17}, +#line 58 "std-name-hint.gperf" + {"weak_ordering", "<compare>", cxx20}, +#line 55 "std-name-hint.gperf" + {"weak_equality", "<compare>", cxx20}, +#line 215 "std-name-hint.gperf" + {"shared_lock", "<shared_mutex>", cxx14}, +#line 50 "std-name-hint.gperf" + {"atomic_flag", "<atomic>", cxx11}, +#line 142 "std-name-hint.gperf" + {"wclog", "<iostream>", cxx98}, +#line 65 "std-name-hint.gperf" + {"condition_variable_any", "<condition_variable>", cxx11}, +#line 139 "std-name-hint.gperf" + {"clog", "<iostream>", cxx98}, +#line 262 "std-name-hint.gperf" + {"type_identity", "<type_traits>", cxx20}, +#line 233 "std-name-hint.gperf" + {"wstring", "<string>", cxx98}, +#line 57 "std-name-hint.gperf" + {"partial_ordering", "<compare>", cxx20} + }; + + static const short lookup[] = + { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, 1, -1, 2, + -1, 3, -1, -228, -1, 6, -201, -2, + -1, 7, 8, -1, 9, -1, -1, -1, + -1, -1, -1, 10, 11, -1, -1, 12, + -1, 13, -1, 14, 15, -1, 16, -1, + 17, -1, -1, 18, 19, 20, -1, 21, + -1, 22, -1, -1, 23, 24, -287, -1, + 27, 28, 29, 30, 31, -1, 32, -1, + 33, 34, 35, 36, 37, -1, 38, -1, + 39, -180, -2, -1, -1, -1, 40, -1, + 41, -1, -1, -1, -1, 42, 43, -1, + 44, 45, 46, -1, 47, -1, 48, 49, + 50, 51, 52, 53, -1, -1, 54, -1, + -1, 55, 56, 57, 58, -1, 59, -1, + 60, 61, -1, 62, -1, 63, 64, -1, + 65, -1, -1, -1, 66, -1, -1, 67, + 68, 69, 70, -1, -1, 71, -1, -1, + 72, -1, 73, -1, -1, 74, 75, -1, + -1, 76, -1, 77, 78, 79, -1, 80, + 81, -1, -1, -1, -1, 82, -1, -1, + 83, -1, -1, 84, -1, 85, 86, 87, + -1, 88, 89, -1, 90, -1, -1, 91, + 92, 93, -1, 94, 95, 96, -1, 97, + -403, 100, 101, -1, 102, -107, -2, 103, + -1, -1, -1, 104, 105, 106, 107, -1, + -1, -1, -1, 108, -1, 109, 110, 111, + 112, 113, 114, 115, -1, -1, 116, 117, + -1, -1, -1, 118, 119, 120, -1, -1, + -1, -1, 121, -1, 122, -1, 123, 124, + 125, 126, -1, 127, 128, -1, -1, -1, + 129, -1, -1, -1, -1, 130, 131, -1, + -1, -1, 132, -1, 133, -1, 134, 135, + 136, -1, -1, -1, 137, -1, 138, -1, + -1, 139, -1, -1, 140, 141, -1, -1, + -1, -1, 142, 143, -1, -1, -1, 144, + 145, -1, -1, -1, -1, 146, 147, 148, + -1, -1, 149, -1, -1, 150, 151, 152, + 153, -1, -1, 154, 155, -1, -1, -1, + -1, 156, 157, 158, 159, 160, 161, -1, + -1, -1, -1, -1, 162, -1, -1, -1, + -1, -1, -1, 163, 164, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 165, 166, 167, -1, -1, -1, + 168, 169, -1, -1, 170, -1, -1, 171, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 172, -1, -1, -1, + 173, 174, 175, -1, -1, -1, -1, 176, + 177, -1, -1, -1, -1, 178, -1, -1, + -1, 179, -1, 180, -1, -1, -1, -1, + -1, 181, -1, -1, -1, -1, 182, -1, + -1, 183, -1, -1, -1, -620, -21, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + 186, -1, -1, 187, -1, -1, -1, 188, + -1, 189, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 190, -1, 191, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 192, + -1, -1, -1, -1, 193, -1, -1, 194, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 195, -1, -1, -1, 196, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 197, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 198, -1, -1, -1, -1, + -1, -1, 199, -1, 200, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 201, -1, -1, -1, -1, -1, -1, + -1, -1, 202, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 203, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 204 + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + unsigned int key = hash (str, len); + + if (key <= MAX_HASH_VALUE) + { + int index = lookup[key]; + + if (index >= 0) + { + const char *s = wordlist[index].name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return &wordlist[index]; + } + else if (index < -TOTAL_KEYWORDS) + { + int offset = - 1 - TOTAL_KEYWORDS - index; + const struct std_name_hint *wordptr = &wordlist[TOTAL_KEYWORDS + lookup[offset]]; + const struct std_name_hint *wordendptr = wordptr + -lookup[offset + 1]; + + while (wordptr < wordendptr) + { + const char *s = wordptr->name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return wordptr; + wordptr++; + } + } + } + } + return 0; +} diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 7fde65a..b99947c 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -8897,7 +8897,56 @@ cp_build_c_cast (location_t loc, tree type, tree expr, return error_mark_node; } - + +/* Warn when a value is moved to itself with std::move. LHS is the target, + RHS may be the std::move call, and LOC is the location of the whole + assignment. */ + +static void +maybe_warn_self_move (location_t loc, tree lhs, tree rhs) +{ + if (!warn_self_move) + return; + + /* C++98 doesn't know move. */ + if (cxx_dialect < cxx11) + return; + + if (processing_template_decl) + return; + + if (!REFERENCE_REF_P (rhs) + || TREE_CODE (TREE_OPERAND (rhs, 0)) != CALL_EXPR) + return; + tree fn = TREE_OPERAND (rhs, 0); + if (!is_std_move_p (fn)) + return; + + /* Just a little helper to strip * and various NOPs. */ + auto extract_op = [] (tree &op) { + STRIP_NOPS (op); + while (INDIRECT_REF_P (op)) + op = TREE_OPERAND (op, 0); + op = maybe_undo_parenthesized_ref (op); + STRIP_ANY_LOCATION_WRAPPER (op); + }; + + tree arg = CALL_EXPR_ARG (fn, 0); + extract_op (arg); + if (TREE_CODE (arg) == ADDR_EXPR) + arg = TREE_OPERAND (arg, 0); + tree type = TREE_TYPE (lhs); + tree orig_lhs = lhs; + extract_op (lhs); + if (cp_tree_equal (lhs, arg)) + { + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wself_move, + "moving %qE of type %qT to itself", orig_lhs, type)) + inform (loc, "remove %<std::move%> call"); + } +} + /* For use from the C common bits. */ tree build_modify_expr (location_t location, @@ -9101,6 +9150,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, if (modifycode == NOP_EXPR) { + maybe_warn_self_move (loc, lhs, rhs); + if (c_dialect_objc ()) { result = objc_maybe_build_modify_expr (lhs, rhs); diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index ebb6391..eae3ac1 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,14 @@ +2022-08-27 Iain Buclaw <ibuclaw@gdcproject.org> + + * dmd/MERGE: Merge upstream dmd 817610b16d. + * d-ctfloat.cc (CTFloat::parse): Update for new front-end interface. + * d-lang.cc (d_parse_file): Likewise. + * expr.cc (ExprVisitor::visit (AssignExp *)): Remove handling of array + assignments to non-trivial static and dynamic arrays. + * runtime.def (ARRAYASSIGN): Remove. + (ARRAYASSIGN_L): Remove. + (ARRAYASSIGN_R): Remove. + 2022-08-16 Iain Buclaw <ibuclaw@gdcproject.org> PR d/106638 diff --git a/gcc/d/d-ctfloat.cc b/gcc/d/d-ctfloat.cc index c4d9a44..a434af9 100644 --- a/gcc/d/d-ctfloat.cc +++ b/gcc/d/d-ctfloat.cc @@ -85,14 +85,13 @@ CTFloat::isInfinity (real_t r) /* Return a real_t value from string BUFFER rounded to long double mode. */ real_t -CTFloat::parse (const char *buffer, bool *overflow) +CTFloat::parse (const char *buffer, bool &overflow) { real_t r; real_from_string3 (&r.rv (), buffer, TYPE_MODE (long_double_type_node)); /* Front-end checks overflow to see if the value is representable. */ - if (overflow && r == target.RealProperties.infinity) - *overflow = true; + overflow = (r == target.RealProperties.infinity) ? true : false; return r; } diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 04147ed..dcc465f 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -1191,7 +1191,6 @@ d_parse_file (void) } /* Do deferred semantic analysis. */ - Module::dprogress = 1; Module::runDeferredSemantic (); if (Module::deferred.length) diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index c358b69..85fc49d 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -d7772a236983ec37b92d21b28bad3cd2de57b945 +817610b16d0f0f469b9fbb28c000956fb910c43f The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md index 50c5ac3..1c7e1dd 100644 --- a/gcc/d/dmd/README.md +++ b/gcc/d/dmd/README.md @@ -18,10 +18,10 @@ this license for that file. | Folder | Purpose | |--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [dmd/](https://github.com/dlang/dmd/tree/master/src/dmd) | The dmd driver and front-end | -| [dmd/backend/](https://github.com/dlang/dmd/tree/master/src/dmd/backend) | Code generation for x86 or x86-64. Shared by the [Digital Mars C compiler](https://github.com/DigitalMars/Compiler/), but not [LDC](https://github.com/ldc-developers/ldc) or [GDC](https://gdcproject.org/). | -| [dmd/common/](https://github.com/dlang/dmd/tree/master/src/dmd/common) | Code shared by the front-end and back-end | -| [dmd/root/](https://github.com/dlang/dmd/tree/master/src/dmd/root) | Meant as a portable utility library, but ["it wasn't very good and the only project left using it is dmd"](https://github.com/dlang/dmd/pull/9844#issuecomment-498479516). | +| [dmd/](https://github.com/dlang/dmd/tree/master/compiler/src/dmd) | The dmd driver and front-end | +| [dmd/backend/](https://github.com/dlang/dmd/tree/master/compiler/src/dmd/backend) | Code generation for x86 or x86-64. Shared by the [Digital Mars C compiler](https://github.com/DigitalMars/Compiler/), but not [LDC](https://github.com/ldc-developers/ldc) or [GDC](https://gdcproject.org/). | +| [dmd/common/](https://github.com/dlang/dmd/tree/master/compiler/src/dmd/common) | Code shared by the front-end and back-end | +| [dmd/root/](https://github.com/dlang/dmd/tree/master/compiler/src/dmd/root) | Meant as a portable utility library, but ["it wasn't very good and the only project left using it is dmd"](https://github.com/dlang/dmd/pull/9844#issuecomment-498479516). | DMD has a mostly flat directory structure, so this section aims to divide all source files into logical groups for easier navigation. The groups are roughly ordered by how late they appear in the compilation process. @@ -31,26 +31,26 @@ Note that these groups have no strict meaning, the category assignments are a bi | File | Purpose | |-----------------------------------------------------------------------------|-----------------------------------------------------------------------| -| [mars.d](https://github.com/dlang/dmd/blob/master/src/dmd/mars.d) | The entry point. Contains `main`. | -| [cli.d](https://github.com/dlang/dmd/blob/master/src/dmd/cli.d) | Define the command line interface | -| [dmdparams.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmdparams.d) | DMD-specific parameters | -| [globals.d](https://github.com/dlang/dmd/blob/master/src/dmd/globals.d) | Define a structure storing command line options | -| [dinifile.d](https://github.com/dlang/dmd/blob/master/src/dmd/dinifile.d) | Parse settings from .ini file (`sc.ini` / `dmd.conf`) | -| [vsoptions.d](https://github.com/dlang/dmd/blob/master/src/dmd/vsoptions.d) | Detect the Microsoft Visual Studio toolchain for linking | -| [frontend.d](https://github.com/dlang/dmd/blob/master/src/dmd/frontend.d) | An interface for using DMD as a library | -| [errors.d](https://github.com/dlang/dmd/blob/master/src/dmd/errors.d) | Error reporting functionality | -| [target.d](https://github.com/dlang/dmd/blob/master/src/dmd/target.d) | Manage target-specific parameters for cross-compiling (for LDC/GDC) | -| [compiler.d](https://github.com/dlang/dmd/blob/master/src/dmd/compiler.d) | Describe a back-end compiler and implements compiler-specific actions | +| [mars.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mars.d) | The entry point. Contains `main`. | +| [cli.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cli.d) | Define the command line interface | +| [dmdparams.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmdparams.d) | DMD-specific parameters | +| [globals.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/globals.d) | Define a structure storing command line options | +| [dinifile.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dinifile.d) | Parse settings from .ini file (`sc.ini` / `dmd.conf`) | +| [vsoptions.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/vsoptions.d) | Detect the Microsoft Visual Studio toolchain for linking | +| [frontend.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/frontend.d) | An interface for using DMD as a library | +| [errors.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errors.d) | Error reporting functionality | +| [target.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/target.d) | Manage target-specific parameters for cross-compiling (for LDC/GDC) | +| [compiler.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/compiler.d) | Describe a back-end compiler and implements compiler-specific actions | ### Lexing / parsing | File | Purpose | |-----------------------------------------------------------------------|----------------------------------------------------------------------| -| [lexer.d](https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d) | Convert source code into tokens for the D and ImportC parsers | -| [entity.d](https://github.com/dlang/dmd/blob/master/src/dmd/entity.d) | Define "\\&Entity;" escape sequence for strings / character literals | -| [tokens.d](https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d) | Define lexical tokens. | -| [parse.d](https://github.com/dlang/dmd/blob/master/src/dmd/parse.d) | D parser, converting tokens into an Abstract Syntax Tree (AST) | -| [cparse.d](https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d) | ImportC parser, converting tokens into an Abstract Syntax Tree (AST) | +| [lexer.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/lexer.d) | Convert source code into tokens for the D and ImportC parsers | +| [entity.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/entity.d) | Define "\\&Entity;" escape sequence for strings / character literals | +| [tokens.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/tokens.d) | Define lexical tokens. | +| [parse.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/parse.d) | D parser, converting tokens into an Abstract Syntax Tree (AST) | +| [cparse.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cparse.d) | ImportC parser, converting tokens into an Abstract Syntax Tree (AST) | ### Semantic analysis @@ -58,88 +58,88 @@ Note that these groups have no strict meaning, the category assignments are a bi | File | Purpose | |---------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------| -| [dsymbol.d](https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.d) | Base class for a D symbol, e.g. a variable, function, module, enum etc. | -| [identifier.d](https://github.com/dlang/dmd/blob/master/src/dmd/identifier.d) | Represents the name of a `Dsymbol` | -| [id.d](https://github.com/dlang/dmd/blob/master/src/dmd/id.d) | Define strings for pre-defined identifiers (e.g. `sizeof`, `string`) | -| [dscope.d](https://github.com/dlang/dmd/blob/master/src/dmd/dscope.d) | Define a 'scope' on which symbol lookup can be performed | -| [dtemplate.d](https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d) | A template declaration or instance | -| [dmodule.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmodule.d) | Define a package and module | -| [mtype.d](https://github.com/dlang/dmd/blob/master/src/dmd/mtype.d) | Define expression types such as `int`, `char[]`, `void function()` | -| [arraytypes.d](https://github.com/dlang/dmd/blob/master/src/dmd/arraytypes.d) | For certain Declaration nodes of type `T`, provides aliases for `Array!T` | -| [declaration.d](https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d) | Misc. declarations of `alias`, variables, type tuples, `ClassInfo` etc. | -| [denum.d](https://github.com/dlang/dmd/blob/master/src/dmd/denum.d) | Defines `enum` declarations and enum members | -| [attrib.d](https://github.com/dlang/dmd/blob/master/src/dmd/nogc.d) | Declarations of 'attributes' such as `private`, `pragma()`, `immutable`, `@UDA`, `align`, `extern(C++)` and more | -| [func.d](https://github.com/dlang/dmd/blob/master/src/dmd/func.d) | Define a function declaration (includes function literals, `invariant`, `unittest`) | -| [dversion.d](https://github.com/dlang/dmd/blob/master/src/dmd/dversion.d) | Defines a version symbol, e.g. `version = ident`, `debug = ident` | +| [dsymbol.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbol.d) | Base class for a D symbol, e.g. a variable, function, module, enum etc. | +| [identifier.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/identifier.d) | Represents the name of a `Dsymbol` | +| [id.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/id.d) | Define strings for pre-defined identifiers (e.g. `sizeof`, `string`) | +| [dscope.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dscope.d) | Define a 'scope' on which symbol lookup can be performed | +| [dtemplate.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dtemplate.d) | A template declaration or instance | +| [dmodule.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmodule.d) | Define a package and module | +| [mtype.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mtype.d) | Define expression types such as `int`, `char[]`, `void function()` | +| [arraytypes.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/arraytypes.d) | For certain Declaration nodes of type `T`, provides aliases for `Array!T` | +| [declaration.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/declaration.d) | Misc. declarations of `alias`, variables, type tuples, `ClassInfo` etc. | +| [denum.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/denum.d) | Defines `enum` declarations and enum members | +| [attrib.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nogc.d) | Declarations of 'attributes' such as `private`, `pragma()`, `immutable`, `@UDA`, `align`, `extern(C++)` and more | +| [func.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/func.d) | Define a function declaration (includes function literals, `invariant`, `unittest`) | +| [dversion.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dversion.d) | Defines a version symbol, e.g. `version = ident`, `debug = ident` | **AST nodes** | File | Purpose | |-----------------------------------------------------------------------------------|-------------------------------------------------------------| -| [ast_node.d](https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d) | Define an abstract AST node class | -| [astbase.d](https://github.com/dlang/dmd/blob/master/src/dmd/astbase.d) | Namespace of AST nodes that can be produced by the parser | -| [astcodegen.d](https://github.com/dlang/dmd/blob/master/src/dmd/astcodegen.d) | Namespace of AST nodes of a AST ready for code generation | -| [astenums.d](https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d) | Enums common to DMD and AST | -| [expression.d](https://github.com/dlang/dmd/blob/master/src/dmd/expression.d) | Define expression AST nodes | -| [statement.d](https://github.com/dlang/dmd/blob/master/src/dmd/statement.d) | Define statement AST nodes | -| [staticassert.d](https://github.com/dlang/dmd/blob/master/src/dmd/staticassert.d) | Define a `static assert` AST node | -| [aggregate.d](https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.d) | Define an aggregate (`struct`, `union` or `class`) AST node | -| [dclass.d](https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d) | Define a `class` AST node | -| [dstruct.d](https://github.com/dlang/dmd/blob/master/src/dmd/dstruct.d) | Define a `struct` or `union` AST node | -| [init.d](https://github.com/dlang/dmd/blob/master/src/dmd/init.d) | Define variable initializers | +| [ast_node.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ast_node.d) | Define an abstract AST node class | +| [astbase.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/astbase.d) | Namespace of AST nodes that can be produced by the parser | +| [astcodegen.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/astcodegen.d) | Namespace of AST nodes of a AST ready for code generation | +| [astenums.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/astenums.d) | Enums common to DMD and AST | +| [expression.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expression.d) | Define expression AST nodes | +| [statement.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statement.d) | Define statement AST nodes | +| [staticassert.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticassert.d) | Define a `static assert` AST node | +| [aggregate.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/aggregate.d) | Define an aggregate (`struct`, `union` or `class`) AST node | +| [dclass.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dclass.d) | Define a `class` AST node | +| [dstruct.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dstruct.d) | Define a `struct` or `union` AST node | +| [init.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/init.d) | Define variable initializers | **AST visitors** | File | Purpose | |-----------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| -| [parsetimevisitor.d](https://github.com/dlang/dmd/blob/master/src/dmd/parsetimevisitor.d) | General [visitor](https://en.wikipedia.org/wiki/Visitor_pattern) for AST nodes | -| [permissivevisitor.d](https://github.com/dlang/dmd/blob/master/src/dmd/permissivevisitor.d) | Subclass of ParseTimeVisitor that does not `assert(0)` on unimplemented nodes | -| [strictvisitor.d](https://github.com/dlang/dmd/blob/master/src/dmd/strictvisitor.d) | Visitor that forces derived classes to implement `visit` for every possible node | -| [visitor.d](https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d) | A visitor implementing `visit` for all nodes present in the compiler | -| [transitivevisitor.d](https://github.com/dlang/dmd/blob/master/src/dmd/transitivevisitor.d) | Provide a mixin template with visit methods for the parse time AST | -| [apply.d](https://github.com/dlang/dmd/blob/master/src/dmd/apply.d) | Depth-first expression visitor | -| [sapply.d](https://github.com/dlang/dmd/blob/master/src/dmd/sapply.d) | Depth-first statement visitor | -| [statement_rewrite_walker.d](https://github.com/dlang/dmd/blob/master/src/dmd/statement_rewrite_walker.d) | Statement visitor that allows replacing the currently visited node | +| [parsetimevisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/parsetimevisitor.d) | General [visitor](https://en.wikipedia.org/wiki/Visitor_pattern) for AST nodes | +| [permissivevisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/permissivevisitor.d) | Subclass of ParseTimeVisitor that does not `assert(0)` on unimplemented nodes | +| [strictvisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/strictvisitor.d) | Visitor that forces derived classes to implement `visit` for every possible node | +| [visitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor.d) | A visitor implementing `visit` for all nodes present in the compiler | +| [transitivevisitor.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/transitivevisitor.d) | Provide a mixin template with visit methods for the parse time AST | +| [apply.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/apply.d) | Depth-first expression visitor | +| [sapply.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/sapply.d) | Depth-first statement visitor | +| [statement_rewrite_walker.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statement_rewrite_walker.d) | Statement visitor that allows replacing the currently visited node | **Semantic passes** | File | Purpose | |-------------------------------------------------------------------------------------------|-------------------------------------------------------------------| -| [dsymbolsem.d](https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d) | Do semantic 1 pass (symbol identifiers/types) | -| [semantic2.d](https://github.com/dlang/dmd/blob/master/src/dmd/semantic2.d) | Do semantic 2 pass (symbol initializers) | -| [semantic3.d](https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d) | Do semantic 3 pass (function bodies) | -| [inline.d](https://github.com/dlang/dmd/blob/master/src/dmd/inline.d) | Do inline pass (optimization pass that dmd does in the front-end) | -| [inlinecost.d](https://github.com/dlang/dmd/blob/master/src/dmd/inlinecost.d) | Compute the cost of inlining a function call. | -| [expressionsem.d](https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d) | Do semantic analysis for expressions | -| [statementsem.d](https://github.com/dlang/dmd/blob/master/src/dmd/statementsem.d) | Do semantic analysis for statements | -| [initsem.d](https://github.com/dlang/dmd/blob/master/src/dmd/initsem.d) | Do semantic analysis for initializers | -| [templateparamsem.d](https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d) | Do semantic analysis for template parameters | -| [typesem.d](https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d) | Do semantic analysis for types | +| [dsymbolsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d) | Do semantic 1 pass (symbol identifiers/types) | +| [semantic2.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic2.d) | Do semantic 2 pass (symbol initializers) | +| [semantic3.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic3.d) | Do semantic 3 pass (function bodies) | +| [inline.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inline.d) | Do inline pass (optimization pass that dmd does in the front-end) | +| [inlinecost.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inlinecost.d) | Compute the cost of inlining a function call. | +| [expressionsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expressionsem.d) | Do semantic analysis for expressions | +| [statementsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statementsem.d) | Do semantic analysis for statements | +| [initsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/initsem.d) | Do semantic analysis for initializers | +| [templateparamsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templateparamsem.d) | Do semantic analysis for template parameters | +| [typesem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typesem.d) | Do semantic analysis for types | **Semantic helpers** | File | Purpose | |-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| -| [opover.d](https://github.com/dlang/dmd/blob/master/src/dmd/opover.d) | Operator overloading | -| [clone.d](https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d) | Generate automatic `opEquals`, `opAssign` and constructors for structs | -| [blockexit.d](https://github.com/dlang/dmd/blob/master/src/dmd/blockexit.d) | Find out in what ways control flow can exit a block | -| [ctorflow.d](https://github.com/dlang/dmd/blob/master/src/dmd/ctorflow.d) | Control flow in constructors | -| [constfold.d](https://github.com/dlang/dmd/blob/master/src/dmd/constfold.d) | Do constant folding of arithmetic expressions | -| [optimize.d](https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d) | Do constant folding more generally | -| [dcast.d](https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d) | Implicit or explicit cast(), finding common types e.g. in `x ? a : b`, integral promotions | -| [impcnvtab.d](https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d) | Define an implicit conversion table for basic types | -| [importc.d](https://github.com/dlang/dmd/blob/master/src/dmd/importc.d) | Helpers specific to ImportC | -| [sideeffect.d](https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d) | Extract side-effects of expressions for certain lowerings. | -| [mustuse.d](https://github.com/dlang/dmd/blob/master/src/dmd/mustuse.d) | Helpers related to the `@mustuse` attribute | +| [opover.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/opover.d) | Operator overloading | +| [clone.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d) | Generate automatic `opEquals`, `opAssign` and constructors for structs | +| [blockexit.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/blockexit.d) | Find out in what ways control flow can exit a block | +| [ctorflow.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ctorflow.d) | Control flow in constructors | +| [constfold.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/constfold.d) | Do constant folding of arithmetic expressions | +| [optimize.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/optimize.d) | Do constant folding more generally | +| [dcast.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dcast.d) | Implicit or explicit cast(), finding common types e.g. in `x ? a : b`, integral promotions | +| [impcnvtab.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/impcnvtab.d) | Define an implicit conversion table for basic types | +| [importc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/importc.d) | Helpers specific to ImportC | +| [sideeffect.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/sideeffect.d) | Extract side-effects of expressions for certain lowerings. | +| [mustuse.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mustuse.d) | Helpers related to the `@mustuse` attribute | **Compile Time Function Execution (CTFE)** | File | Purpose | |-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| -| [dinterpret.d](https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d) | CTFE entry point | -| [ctfeexpr.d](https://github.com/dlang/dmd/blob/master/src/dmd/ctfeexpr.d) | CTFE for expressions involving pointers, slices, array concatenation etc. | -| [builtin.d](https://github.com/dlang/dmd/blob/master/src/dmd/builtin.d) | Allow CTFE of certain external functions (`core.math`, `std.math` and `core.bitop`) | +| [dinterpret.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dinterpret.d) | CTFE entry point | +| [ctfeexpr.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ctfeexpr.d) | CTFE for expressions involving pointers, slices, array concatenation etc. | +| [builtin.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/builtin.d) | Allow CTFE of certain external functions (`core.math`, `std.math` and `core.bitop`) | ### Specific language features @@ -147,116 +147,116 @@ Note that these groups have no strict meaning, the category assignments are a bi | File | Purpose | |---------------------------------------------------------------------------|----------------------------------------| -| [nogc.d](https://github.com/dlang/dmd/blob/master/src/dmd/nogc.d) | `@nogc` checks | -| [safe.d](https://github.com/dlang/dmd/blob/master/src/dmd/safe.d) | `@safe` checks | -| [canthrow.d](https://github.com/dlang/dmd/blob/master/src/dmd/canthrow.d) | `nothrow` checks | -| [escape.d](https://github.com/dlang/dmd/blob/master/src/dmd/escape.d) | `scope` checks | -| [access.d](https://github.com/dlang/dmd/blob/master/src/dmd/access.d) | `public` / `private` checks | -| [ob.d](https://github.com/dlang/dmd/blob/master/src/dmd/ob.d) | Ownership / borrowing (`@live`) checks | +| [nogc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nogc.d) | `@nogc` checks | +| [safe.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/safe.d) | `@safe` checks | +| [canthrow.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/canthrow.d) | `nothrow` checks | +| [escape.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/escape.d) | `scope` checks | +| [access.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/access.d) | `public` / `private` checks | +| [ob.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ob.d) | Ownership / borrowing (`@live`) checks | **Inline Assembly** | File | Purpose | |-------------------------------------------------------------------------|-------------------------------------------| -| [iasm.d](https://github.com/dlang/dmd/blob/master/src/dmd/iasm.d) | Inline assembly depending on the compiler | -| [iasmdmd.d](https://github.com/dlang/dmd/blob/master/src/dmd/iasmdmd.d) | Inline assembly for DMD | -| [iasmgcc.d](https://github.com/dlang/dmd/blob/master/src/dmd/iasmgcc.d) | Inline assembly for GDC | +| [iasm.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/iasm.d) | Inline assembly depending on the compiler | +| [iasmdmd.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/iasmdmd.d) | Inline assembly for DMD | +| [iasmgcc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/iasmgcc.d) | Inline assembly for GDC | **Other** | File | Purpose | |--------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------| -| [aliasthis.d](https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d) | Resolve implicit conversions for `alias X this` | -| [traits.d](https://github.com/dlang/dmd/blob/master/src/dmd/traits.d) | `__traits()` | -| [lambdacomp.d](https://github.com/dlang/dmd/blob/master/src/dmd/lambdacomp.d) | `__traits(isSame, x => y, z => w)` | -| [cond.d](https://github.com/dlang/dmd/blob/master/src/dmd/cond.d) | Evaluate `static if`, `version` `debug ` | -| [staticcond.d](https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d) | Lazily evaluate static conditions for `static if`, `static assert` and template constraints | -| [delegatize.d](https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d) | Converts expression to delegates for `lazy` parameters | -| [eh.d](https://github.com/dlang/dmd/blob/master/src/dmd/eh.d) | Generate tables for exception handling | -| [nspace.d](https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d) | Namespace for `extern (C++, Module)` | -| [intrange.d](https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d) | [Value range propagation](https://digitalmars.com/articles/b62.html) | -| [dimport.d](https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d) | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`) | -| [arrayop.d](https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d) | Array operations (`a[] = b[] + c[]`) | -| [cpreprocess.d](https://github.com/dlang/dmd/blob/master/src/dmd/cpreprocess.d)| Run the C preprocessor on C source files | -| [typinf.d](https://github.com/dlang/dmd/blob/master/src/dmd/typinf.d) | Generate typeinfo for `typeid()` (as well as internals) | +| [aliasthis.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/aliasthis.d) | Resolve implicit conversions for `alias X this` | +| [traits.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/traits.d) | `__traits()` | +| [lambdacomp.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/lambdacomp.d) | `__traits(isSame, x => y, z => w)` | +| [cond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cond.d) | Evaluate `static if`, `version` `debug ` | +| [staticcond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticcond.d) | Lazily evaluate static conditions for `static if`, `static assert` and template constraints | +| [delegatize.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/delegatize.d) | Converts expression to delegates for `lazy` parameters | +| [eh.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/eh.d) | Generate tables for exception handling | +| [nspace.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nspace.d) | Namespace for `extern (C++, Module)` | +| [intrange.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/intrange.d) | [Value range propagation](https://digitalmars.com/articles/b62.html) | +| [dimport.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dimport.d) | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`) | +| [arrayop.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/arrayop.d) | Array operations (`a[] = b[] + c[]`) | +| [cpreprocess.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cpreprocess.d)| Run the C preprocessor on C source files | +| [typinf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typinf.d) | Generate typeinfo for `typeid()` (as well as internals) | | File | Purpose | |-----------------------------------------------------------------------------|------------------------------------------------------------------------------------| -| [chkformat.d](https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d) | Validate arguments with format specifiers for `printf` / `scanf` etc. | -| [imphint.d](https://github.com/dlang/dmd/blob/master/src/dmd/imphint.d) | Give a suggestion to e.g. `import std.stdio` when `writeln` could not be resolved. | +| [chkformat.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/chkformat.d) | Validate arguments with format specifiers for `printf` / `scanf` etc. | +| [imphint.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/imphint.d) | Give a suggestion to e.g. `import std.stdio` when `writeln` could not be resolved. | ### Library files | File | Purpose | |-------------------------------------------------------------------------------|------------------------------------------------------| -| [lib.d](https://github.com/dlang/dmd/blob/master/src/dmd/lib.d) | Abstract library class | -| [libelf.d](https://github.com/dlang/dmd/blob/master/src/dmd/libelf.d) | Library in ELF format (Unix) | -| [libmach.d](https://github.com/dlang/dmd/blob/master/src/dmd/libmach.d) | Library in Mach-O format (macOS) | -| [libmscoff.d](https://github.com/dlang/dmd/blob/master/src/dmd/libmscoff.d) | Library in COFF format (32/64-bit Windows) | -| [libomf.d](https://github.com/dlang/dmd/blob/master/src/dmd/libomf.d) | Library in OMF format (legacy 32-bit Windows) | -| [scanelf.d](https://github.com/dlang/dmd/blob/master/src/dmd/scanelf.d) | Extract symbol names from a library in ELF format | -| [scanmach.d](https://github.com/dlang/dmd/blob/master/src/dmd/scanmach.d) | Extract symbol names from a library in Mach-O format | -| [scanmscoff.d](https://github.com/dlang/dmd/blob/master/src/dmd/scanmscoff.d) | Extract symbol names from a library in COFF format | -| [scanomf.d](https://github.com/dlang/dmd/blob/master/src/dmd/scanomf.d) | Extract symbol names from a library in OMF format | +| [lib.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/lib.d) | Abstract library class | +| [libelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libelf.d) | Library in ELF format (Unix) | +| [libmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmach.d) | Library in Mach-O format (macOS) | +| [libmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libmscoff.d) | Library in COFF format (32/64-bit Windows) | +| [libomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/libomf.d) | Library in OMF format (legacy 32-bit Windows) | +| [scanelf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanelf.d) | Extract symbol names from a library in ELF format | +| [scanmach.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmach.d) | Extract symbol names from a library in Mach-O format | +| [scanmscoff.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanmscoff.d) | Extract symbol names from a library in COFF format | +| [scanomf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/scanomf.d) | Extract symbol names from a library in OMF format | ### Code generation / back-end interfacing | File | Purpose | |---------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| -| [dmsc.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmsc.d) | Configures and initializes the back-end | -| [toobj.d](https://github.com/dlang/dmd/blob/master/src/dmd/toobj.d) | Convert an AST that went through all semantic phases into an object file | -| [toir.d](https://github.com/dlang/dmd/blob/master/src/dmd/toir.d) | Convert Dsymbols intermediate representation | -| [e2ir.d](https://github.com/dlang/dmd/blob/master/src/dmd/e2ir.d) | Convert Expressions to intermediate representation | -| [s2ir.d](https://github.com/dlang/dmd/blob/master/src/dmd/s2ir.d) | Convert Statements to intermediate representation | -| [stmtstate.d](https://github.com/dlang/dmd/blob/master/src/dmd/stmtstate.d) | Used to help transform statement AST into flow graph | -| [toctype.d](https://github.com/dlang/dmd/blob/master/src/dmd/toctype.d) | Convert a D type to a type the back-end understands | -| [tocsym.d](https://github.com/dlang/dmd/blob/master/src/dmd/tocsym.d) | Convert a D symbol to a symbol the linker understands (with mangled name) | -| [argtypes_x86.d](https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_x86.d) | Convert a D type into simple (register) types for the 32-bit x86 ABI | -| [argtypes_sysv_x64.d](https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_sysv_x64.d) | 'argtypes' for the x86_64 System V ABI | -| [argtypes_aarch64.d](https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_aarch64.d) | 'argtypes' for the AArch64 ABI | -| [glue.d](https://github.com/dlang/dmd/blob/master/src/dmd/glue.d) | Generate the object file for function declarations | -| [gluelayer.d](https://github.com/dlang/dmd/blob/master/src/dmd/gluelayer.d) | Declarations for back-end functions that the front-end invokes | -| [todt.d](https://github.com/dlang/dmd/blob/master/src/dmd/todt.d) | Convert initializers into structures that the back-end will add to the data segment | -| [tocvdebug.d](https://github.com/dlang/dmd/blob/master/src/dmd/tovcdebug.d) | Generate debug info in the CV4 debug format. | -| [objc.d](https://github.com/dlang/dmd/blob/master/src/dmd/objc.d) | Objective-C interfacing | -| [objc_glue.d](https://github.com/dlang/dmd/blob/master/src/dmd/objc_glue.d) | Glue code for Objective-C interop. | +| [dmsc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmsc.d) | Configures and initializes the back-end | +| [toobj.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/toobj.d) | Convert an AST that went through all semantic phases into an object file | +| [toir.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/toir.d) | Convert Dsymbols intermediate representation | +| [e2ir.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/e2ir.d) | Convert Expressions to intermediate representation | +| [s2ir.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/s2ir.d) | Convert Statements to intermediate representation | +| [stmtstate.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/stmtstate.d) | Used to help transform statement AST into flow graph | +| [toctype.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/toctype.d) | Convert a D type to a type the back-end understands | +| [tocsym.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/tocsym.d) | Convert a D symbol to a symbol the linker understands (with mangled name) | +| [argtypes_x86.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_x86.d) | Convert a D type into simple (register) types for the 32-bit x86 ABI | +| [argtypes_sysv_x64.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_sysv_x64.d) | 'argtypes' for the x86_64 System V ABI | +| [argtypes_aarch64.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_aarch64.d) | 'argtypes' for the AArch64 ABI | +| [glue.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/glue.d) | Generate the object file for function declarations | +| [gluelayer.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/gluelayer.d) | Declarations for back-end functions that the front-end invokes | +| [todt.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/todt.d) | Convert initializers into structures that the back-end will add to the data segment | +| [tocvdebug.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/tovcdebug.d) | Generate debug info in the CV4 debug format. | +| [objc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/objc.d) | Objective-C interfacing | +| [objc_glue.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/objc_glue.d) | Glue code for Objective-C interop. | **Name mangling** | File | Purpose | |-----------------------------------------------------------------------------------|------------------------------------------------------------------| -| [cppmangle.d](https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d) | C++ name mangling | -| [cppmanglewin.d](https://github.com/dlang/dmd/blob/master/src/dmd/cppmanglewin.d) | C++ name mangling for Windows | -| [dmangle.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmangle.d) | D [name mangling](https://dlang.org/spec/abi.html#name_mangling) | +| [cppmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmangle.d) | C++ name mangling | +| [cppmanglewin.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cppmanglewin.d) | C++ name mangling for Windows | +| [dmangle.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmangle.d) | D [name mangling](https://dlang.org/spec/abi.html#name_mangling) | ### Linking | File | Purpose | |-------------------------------------------------------------------|-----------------------------------------| -| [link.d](https://github.com/dlang/dmd/blob/master/src/dmd/link.d) | Invoke the linker as a separate process | +| [link.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/link.d) | Invoke the linker as a separate process | ### Special output | File | Purpose | |-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| -| [doc.d](https://github.com/dlang/dmd/blob/master/src/dmd/doc.d) | [Documentation generation](https://dlang.org/spec/ddoc.html) | -| [dmacro.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmacro.d) | DDoc macro processing | -| [hdrgen.d](https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d) | Convert an AST into D source code for `.di` header generation, as well as `-vcg-ast` and error messages | -| [json.d](https://github.com/dlang/dmd/blob/master/src/dmd/json.d) | Describe the module in a `.json` file for the `-X` flag | -| [dtoh.d](https://github.com/dlang/dmd/blob/master/src/dmd/dtoh.d) | C++ header generation from D source files | +| [doc.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/doc.d) | [Documentation generation](https://dlang.org/spec/ddoc.html) | +| [dmacro.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmacro.d) | DDoc macro processing | +| [hdrgen.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/hdrgen.d) | Convert an AST into D source code for `.di` header generation, as well as `-vcg-ast` and error messages | +| [json.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/json.d) | Describe the module in a `.json` file for the `-X` flag | +| [dtoh.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dtoh.d) | C++ header generation from D source files | ### Utility -Note: many other utilities are in [dmd/root](https://github.com/dlang/dmd/tree/master/src/dmd/root). +Note: many other utilities are in [dmd/root](https://github.com/dlang/dmd/tree/master/compiler/src/dmd/root). | File | Purpose | |-----------------------------------------------------------------------------------|---------------------------------------------------| -| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d) | Print error messages in color | -| [file_manager.d](https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d) | Keep file contents in memory | -| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d) | Utility functions related to files and file paths | +| [console.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/console.d) | Print error messages in color | +| [file_manager.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/file_manager.d) | Keep file contents in memory | +| [utils.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/utils.d) | Utility functions related to files and file paths | | File | Purpose | |---------------------------------------------------------------------------------|---------------------------------------------------------------| -| [asttypename.d](https://github.com/dlang/dmd/blob/master/src/dmd/asttypename.d) | Print the internal name of an AST node (for debugging only) | -| [printast.d](https://github.com/dlang/dmd/blob/master/src/dmd/printast.d) | Print the AST data structure | -| [foreachvar.d](https://github.com/dlang/dmd/blob/master/src/dmd/foreachvar.d) | Used in `ob.d` to iterate over all variables in an expression | +| [asttypename.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/asttypename.d) | Print the internal name of an AST node (for debugging only) | +| [printast.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/printast.d) | Print the AST data structure | +| [foreachvar.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/foreachvar.d) | Used in `ob.d` to iterate over all variables in an expression | diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d index bf19693..091e96a 100644 --- a/gcc/d/dmd/astenums.d +++ b/gcc/d/dmd/astenums.d @@ -68,7 +68,6 @@ enum STC : ulong // transfer changes to declaration.h ref_ = 0x4_0000, /// `ref` scope_ = 0x8_0000, /// `scope` - maybescope = 0x10_0000, /// parameter might be `scope` scopeinferred = 0x20_0000, /// `scope` has been inferred and should not be part of mangling, `scope_` must also be set return_ = 0x40_0000, /// 'return ref' or 'return scope' for function parameters returnScope = 0x80_0000, /// if `ref return scope` then resolve to `ref` and `return scope` diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index fe6e1e3..088ca61 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -114,8 +114,10 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN import dmd.id : Id; auto sd = ts.sym; + const id = ce.f.ident; if (sd.postblit && - (ce.f.ident == Id._d_arrayctor || ce.f.ident == Id._d_arraysetctor)) + (id == Id._d_arrayctor || id == Id._d_arraysetctor || + id == Id._d_arrayassign_l || id == Id._d_arrayassign_r)) { checkFuncThrows(ce, sd.postblit); return; diff --git a/gcc/d/dmd/common/README.md b/gcc/d/dmd/common/README.md index fb282dc..853fd4f 100644 --- a/gcc/d/dmd/common/README.md +++ b/gcc/d/dmd/common/README.md @@ -2,7 +2,7 @@ | File | Purpose | |------------------------------------------------------------------------------------|-----------------------------------------------------------------| -| [bitfields.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d) | Pack multiple boolean fields into bit fields | -| [file.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d) | Functions and objects dedicated to file I/O and management | -| [outbuffer.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data | -| [string.d](https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d) | Common string functions including filename manipulation | +| [bitfields.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/bitfields.d) | Pack multiple boolean fields into bit fields | +| [file.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/file.d) | Functions and objects dedicated to file I/O and management | +| [outbuffer.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data | +| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/string.d) | Common string functions including filename manipulation | diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d index 9a5bd82..9d544a4 100644 --- a/gcc/d/dmd/common/outbuffer.d +++ b/gcc/d/dmd/common/outbuffer.d @@ -109,12 +109,12 @@ struct OutBuffer } /// For porting with ease from dmd.backend.outbuf.Outbuffer - ubyte* buf() nothrow { + ubyte* buf() nothrow @system { return data.ptr; } /// For porting with ease from dmd.backend.outbuf.Outbuffer - ubyte** bufptr() nothrow { + ubyte** bufptr() nothrow @system { static struct Array { size_t length; ubyte* ptr; } auto a = cast(Array*) &data; assert(a.length == data.length && a.ptr == data.ptr); @@ -156,7 +156,7 @@ struct OutBuffer Params: nbytes = the number of additional bytes to reserve */ - extern (C++) void reserve(size_t nbytes) pure nothrow + extern (C++) void reserve(size_t nbytes) pure nothrow @trusted { //debug (stomp) printf("OutBuffer::reserve: size = %lld, offset = %lld, nbytes = %lld\n", data.length, offset, nbytes); const minSize = offset + nbytes; @@ -210,7 +210,7 @@ struct OutBuffer offset = 0; } - private void indent() pure nothrow + private void indent() pure nothrow @safe { if (level) { @@ -223,19 +223,19 @@ struct OutBuffer } // Write an array to the buffer, no reserve check - @trusted nothrow + @system nothrow void writen(const void *b, size_t len) { memcpy(data.ptr + offset, b, len); offset += len; } - extern (C++) void write(const(void)* data, size_t nbytes) pure nothrow + extern (C++) void write(const(void)* data, size_t nbytes) pure nothrow @system { write(data[0 .. nbytes]); } - void write(const(void)[] buf) pure nothrow + void write(scope const(void)[] buf) pure nothrow @trusted { if (doindent && !notlinehead) indent(); @@ -282,7 +282,7 @@ struct OutBuffer } /// NOT zero-terminated - extern (C++) void writestring(const(char)* s) pure nothrow + extern (C++) void writestring(const(char)* s) pure nothrow @system { if (!s) return; @@ -291,19 +291,19 @@ struct OutBuffer } /// ditto - void writestring(const(char)[] s) pure nothrow + void writestring(scope const(char)[] s) pure nothrow @safe { write(s); } /// ditto - void writestring(string s) pure nothrow + void writestring(scope string s) pure nothrow @safe { write(s); } /// NOT zero-terminated, followed by newline - void writestringln(const(char)[] s) pure nothrow + void writestringln(const(char)[] s) pure nothrow @safe { writestring(s); writenl(); @@ -311,25 +311,25 @@ struct OutBuffer /** Write string to buffer, ensure it is zero terminated */ - void writeStringz(const(char)* s) pure nothrow @trusted + void writeStringz(const(char)* s) pure nothrow @system { write(s[0 .. strlen(s)+1]); } /// ditto - void writeStringz(const(char)[] s) pure nothrow + void writeStringz(const(char)[] s) pure nothrow @safe { write(s); writeByte(0); } /// ditto - void writeStringz(string s) pure nothrow + void writeStringz(string s) pure nothrow @safe { writeStringz(cast(const(char)[])(s)); } - extern (C++) void prependstring(const(char)* string) pure nothrow + extern (C++) void prependstring(const(char)* string) pure nothrow @system { size_t len = strlen(string); reserve(len); @@ -339,7 +339,7 @@ struct OutBuffer } /// write newline - extern (C++) void writenl() pure nothrow + extern (C++) void writenl() pure nothrow @safe { version (Windows) { @@ -385,7 +385,7 @@ struct OutBuffer this.data[offset++] = cast(ubyte) b; } - extern (C++) void writeByte(uint b) pure nothrow + extern (C++) void writeByte(uint b) pure nothrow @safe { if (doindent && !notlinehead && b != '\n') indent(); @@ -394,7 +394,7 @@ struct OutBuffer offset++; } - extern (C++) void writeUTF8(uint b) pure nothrow + extern (C++) void writeUTF8(uint b) pure nothrow @safe { reserve(6); if (b <= 0x7F) @@ -427,7 +427,7 @@ struct OutBuffer assert(0); } - extern (C++) void prependbyte(uint b) pure nothrow + extern (C++) void prependbyte(uint b) pure nothrow @trusted { reserve(1); memmove(data.ptr + 1, data.ptr, offset); @@ -435,7 +435,7 @@ struct OutBuffer offset++; } - extern (C++) void writewchar(uint w) pure nothrow + extern (C++) void writewchar(uint w) pure nothrow @safe { version (Windows) { @@ -447,7 +447,7 @@ struct OutBuffer } } - extern (C++) void writeword(uint w) pure nothrow + extern (C++) void writeword(uint w) pure nothrow @trusted { version (Windows) { @@ -465,7 +465,7 @@ struct OutBuffer offset += 2; } - extern (C++) void writeUTF16(uint w) pure nothrow + extern (C++) void writeUTF16(uint w) pure nothrow @trusted { reserve(4); if (w <= 0xFFFF) @@ -483,7 +483,7 @@ struct OutBuffer assert(0); } - extern (C++) void write4(uint w) pure nothrow + extern (C++) void write4(uint w) pure nothrow @trusted { version (Windows) { @@ -500,7 +500,7 @@ struct OutBuffer offset += 4; } - extern (C++) void write(const OutBuffer* buf) pure nothrow + extern (C++) void write(const OutBuffer* buf) pure nothrow @trusted { if (buf) { @@ -510,7 +510,7 @@ struct OutBuffer } } - extern (C++) void fill0(size_t nbytes) pure nothrow + extern (C++) void fill0(size_t nbytes) pure nothrow @trusted { reserve(nbytes); memset(data.ptr + offset, 0, nbytes); @@ -531,7 +531,7 @@ struct OutBuffer return cast(char[])data[offset - nbytes .. offset]; } - extern (C++) void vprintf(const(char)* format, va_list args) nothrow + extern (C++) void vprintf(const(char)* format, va_list args) nothrow @system { int count; if (doindent && !notlinehead) @@ -567,7 +567,7 @@ struct OutBuffer static if (__VERSION__ < 2092) { - extern (C++) void printf(const(char)* format, ...) nothrow + extern (C++) void printf(const(char)* format, ...) nothrow @system { va_list ap; va_start(ap, format); @@ -577,7 +577,7 @@ struct OutBuffer } else { - pragma(printf) extern (C++) void printf(const(char)* format, ...) nothrow + pragma(printf) extern (C++) void printf(const(char)* format, ...) nothrow @system { va_list ap; va_start(ap, format); @@ -591,13 +591,13 @@ struct OutBuffer * Params: * u = integral value to append */ - extern (C++) void print(ulong u) pure nothrow + extern (C++) void print(ulong u) pure nothrow @safe { UnsignedStringBuf buf = void; writestring(unsignedToTempString(u, buf)); } - extern (C++) void bracket(char left, char right) pure nothrow + extern (C++) void bracket(char left, char right) pure nothrow @trusted { reserve(2); memmove(data.ptr + 1, data.ptr, offset); @@ -610,7 +610,7 @@ struct OutBuffer * Insert left at i, and right at j. * Return index just past right. */ - extern (C++) size_t bracket(size_t i, const(char)* left, size_t j, const(char)* right) pure nothrow + extern (C++) size_t bracket(size_t i, const(char)* left, size_t j, const(char)* right) pure nothrow @system { size_t leftlen = strlen(left); size_t rightlen = strlen(right); @@ -620,7 +620,7 @@ struct OutBuffer return j + leftlen + rightlen; } - extern (C++) void spread(size_t offset, size_t nbytes) pure nothrow + extern (C++) void spread(size_t offset, size_t nbytes) pure nothrow @system { reserve(nbytes); memmove(data.ptr + offset + nbytes, data.ptr + offset, this.offset - offset); @@ -630,19 +630,19 @@ struct OutBuffer /**************************************** * Returns: offset + nbytes */ - extern (C++) size_t insert(size_t offset, const(void)* p, size_t nbytes) pure nothrow + extern (C++) size_t insert(size_t offset, const(void)* p, size_t nbytes) pure nothrow @system { spread(offset, nbytes); memmove(data.ptr + offset, p, nbytes); return offset + nbytes; } - size_t insert(size_t offset, const(char)[] s) pure nothrow + size_t insert(size_t offset, const(char)[] s) pure nothrow @system { return insert(offset, s.ptr, s.length); } - extern (C++) void remove(size_t offset, size_t nbytes) pure nothrow @nogc + extern (C++) void remove(size_t offset, size_t nbytes) pure nothrow @nogc @system { memmove(data.ptr + offset, data.ptr + offset + nbytes, this.offset - (offset + nbytes)); this.offset -= nbytes; @@ -716,7 +716,7 @@ struct OutBuffer return extractData(); } - void writesLEB128(int value) pure nothrow + void writesLEB128(int value) pure nothrow @safe { while (1) { @@ -733,7 +733,7 @@ struct OutBuffer } } - void writeuLEB128(uint value) pure nothrow + void writeuLEB128(uint value) pure nothrow @safe { do { @@ -758,7 +758,7 @@ struct OutBuffer Returns: `true` iff the operation succeeded. */ - extern(D) bool moveToFile(const char* filename) + extern(D) bool moveToFile(const char* filename) @system { bool result = true; const bool identical = this[] == FileMapping!(const ubyte)(filename)[]; @@ -799,7 +799,7 @@ private: alias UnsignedStringBuf = char[20]; -char[] unsignedToTempString(ulong value, char[] buf, uint radix = 10) @safe pure nothrow @nogc +char[] unsignedToTempString(ulong value, return scope char[] buf, uint radix = 10) @safe pure nothrow @nogc { size_t i = buf.length; do diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d index 11229d4..6243e74 100644 --- a/gcc/d/dmd/ctfeexpr.d +++ b/gcc/d/dmd/ctfeexpr.d @@ -357,15 +357,31 @@ UnionExp copyLiteral(Expression e) r.origin = sle.origin; return ue; } - if (e.op == EXP.function_ || e.op == EXP.delegate_ || e.op == EXP.symbolOffset || e.op == EXP.null_ || e.op == EXP.variable || e.op == EXP.dotVariable || e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.char_ || e.op == EXP.complex80 || e.op == EXP.void_ || e.op == EXP.vector || e.op == EXP.typeid_) - { + + switch(e.op) + { + case EXP.function_: + case EXP.delegate_: + case EXP.symbolOffset: + case EXP.null_: + case EXP.variable: + case EXP.dotVariable: + case EXP.int64: + case EXP.float64: + case EXP.char_: + case EXP.complex80: + case EXP.void_: + case EXP.vector: + case EXP.typeid_: // Simple value types // Keep e1 for DelegateExp and DotVarExp emplaceExp!(UnionExp)(&ue, e); Expression r = ue.exp(); r.type = e.type; return ue; + default: break; } + if (auto se = e.isSliceExp()) { if (se.type.toBasetype().ty == Tsarray) diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index ffb33d3..ff27e37 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -563,8 +563,9 @@ extern (C++) abstract class Declaration : Dsymbol extern (C++) final class TupleDeclaration : Declaration { Objects* objects; - bool isexp; // true: expression tuple TypeTuple tupletype; // !=null if this is a type tuple + bool isexp; // true: expression tuple + bool building; // it's growing in AliasAssign semantic extern (D) this(const ref Loc loc, Identifier ident, Objects* objects) { @@ -588,7 +589,7 @@ extern (C++) final class TupleDeclaration : Declaration */ //printf("TupleDeclaration::getType() %s\n", toChars()); - if (isexp) + if (isexp || building) return null; if (!tupletype) { @@ -931,6 +932,19 @@ extern (C++) final class AliasDeclaration : Declaration } else { + // stop AliasAssign tuple building + if (aliassym) + { + if (auto td = aliassym.isTupleDeclaration()) + { + if (td.building) + { + td.building = false; + semanticRun = PASS.semanticdone; + return td; + } + } + } if (_import && _import._scope) { /* If this is an internal alias for selective/renamed import, @@ -1076,7 +1090,7 @@ extern (C++) class VarDeclaration : Declaration VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection Expression edtor; // if !=null, does the destruction of the variable IntRange* range; // if !=null, the variable is known to be within the range - VarDeclarations* maybes; // STC.maybescope variables that are assigned to this STC.maybescope variable + VarDeclarations* maybes; // maybeScope variables that are assigned to this maybeScope variable uint endlinnum; // line number of end of scope that this var lives in uint offset; @@ -1105,7 +1119,7 @@ extern (C++) class VarDeclaration : Declaration bool overlapped; /// if it is a field and has overlapping bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe - bool doNotInferScope; /// do not infer 'scope' for this variable + bool maybeScope; /// allow inferring 'scope' for this variable bool doNotInferReturn; /// do not infer 'return' for this variable bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index c8f6c2a..bc8db44 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -59,7 +59,6 @@ struct AttributeViolation; #define STCref 0x40000ULL /// `ref` #define STCscope 0x80000ULL /// `scope` - #define STCmaybescope 0x100000ULL /// parameter might be `scope` #define STCscopeinferred 0x200000ULL /// `scope` has been inferred and should not be part of mangling, `scope` must also be set #define STCreturn 0x400000ULL /// 'return ref' or 'return scope' for function parameters #define STCreturnScope 0x800000ULL /// if `ref return scope` then resolve to `ref` and `return scope` @@ -166,9 +165,9 @@ class TupleDeclaration final : public Declaration { public: Objects *objects; - bool isexp; // true: expression tuple - TypeTuple *tupletype; // !=NULL if this is a type tuple + bool isexp; // true: expression tuple + bool building; // it's growing in AliasAssign semantic TupleDeclaration *syntaxCopy(Dsymbol *) override; const char *kind() const override; @@ -264,8 +263,8 @@ public: bool overlapped(bool v); bool overlapUnsafe() const; // if it is an overlapping field and the overlaps are unsafe bool overlapUnsafe(bool v); - bool doNotInferScope() const; // do not infer 'scope' for this variable - bool doNotInferScope(bool v); + bool maybeScope() const; // allow inferring 'scope' for this variable + bool maybeScope(bool v); bool doNotInferReturn() const; // do not infer 'return' for this variable bool doNotInferReturn(bool v); bool isArgDtorVar() const; // temporary created to handle scope destruction of a function argument diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d index 156cce2..5cc3772 100644 --- a/gcc/d/dmd/dimport.d +++ b/gcc/d/dmd/dimport.d @@ -223,7 +223,16 @@ extern (C++) final class Import : Dsymbol override void importAll(Scope* sc) { if (mod) return; // Already done - load(sc); + + /* + * https://issues.dlang.org/show_bug.cgi?id=15525 + * + * Loading the import has failed, + * most likely because of parsing errors. + * Therefore we cannot trust the resulting AST. + */ + if (load(sc)) return; + if (!mod) return; // Failed if (sc.stc & STC.static_) diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 890c3b6..a9fd0f5 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -4778,6 +4778,12 @@ public: // If `_d_HookTraceImpl` is found, resolve the underlying hook and replace `e` and `fd` with it. removeHookTraceImpl(e, fd); + bool isArrayConstructionOrAssign(FuncDeclaration fd) + { + return fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor || + fd.ident == Id._d_arrayassign_l || fd.ident == Id._d_arrayassign_r; + } + if (fd.ident == Id.__ArrayPostblit || fd.ident == Id.__ArrayDtor) { assert(e.arguments.dim == 1); @@ -4831,27 +4837,36 @@ public: result = interpretRegion(ae, istate); return; } - else if (fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor) + else if (isArrayConstructionOrAssign(fd)) { - // In expressionsem.d `T[x] ea = eb;` was lowered to `_d_array{,set}ctor(ea[], eb[]);`. - // The following code will rewrite it back to `ea = eb` and then interpret that expression. - if (fd.ident == Id._d_arraysetctor) - assert(e.arguments.dim == 2); - else + // In expressionsem.d, the following lowerings were performed: + // * `T[x] ea = eb;` to `_d_array{,set}ctor(ea[], eb[]);`. + // * `ea = eb` (ea and eb are arrays) to `_d_arrayassign_{l,r}(ea[], eb[])`. + // The following code will rewrite them back to `ea = eb` and + // then interpret that expression. + + if (fd.ident == Id._d_arrayctor) assert(e.arguments.dim == 3); + else + assert(e.arguments.dim == 2); Expression ea = (*e.arguments)[0]; if (ea.isCastExp) ea = ea.isCastExp.e1; Expression eb = (*e.arguments)[1]; - if (eb.isCastExp && fd.ident == Id._d_arrayctor) + if (eb.isCastExp() && fd.ident != Id._d_arraysetctor) eb = eb.isCastExp.e1; - ConstructExp ce = new ConstructExp(e.loc, ea, eb); - ce.type = ea.type; + Expression rewrittenExp; + if (fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor) + rewrittenExp = new ConstructExp(e.loc, ea, eb); + else + rewrittenExp = new AssignExp(e.loc, ea, eb); + + rewrittenExp.type = ea.type; + result = interpret(rewrittenExp, istate); - result = interpret(ce, istate); return; } else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendTTrace) diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d index 9beac6b..358712b 100644 --- a/gcc/d/dmd/dmacro.d +++ b/gcc/d/dmd/dmacro.d @@ -14,8 +14,6 @@ module dmd.dmacro; import core.stdc.ctype; import core.stdc.string; import dmd.doc; -import dmd.errors; -import dmd.globals; import dmd.common.outbuffer; import dmd.root.rmem; @@ -28,7 +26,7 @@ extern (C++) struct MacroTable * name = name of macro * text = text of macro */ - extern (D) void define(const(char)[] name, const(char)[] text) + extern (D) void define(const(char)[] name, const(char)[] text) nothrow pure @safe { //printf("MacroTable::define('%.*s' = '%.*s')\n", cast(int)name.length, name.ptr, text.length, text.ptr); if (auto table = name in mactab) @@ -42,8 +40,10 @@ extern (C++) struct MacroTable /***************************************************** * Look for macros in buf and expand them in place. * Only look at the text in buf from start to pend. + * + * Returns: `true` on success, `false` when the recursion limit was reached */ - extern (D) void expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg) + extern (D) bool expand(ref OutBuffer buf, size_t start, ref size_t pend, const(char)[] arg, int recursionLimit) nothrow pure { version (none) { @@ -51,14 +51,10 @@ extern (C++) struct MacroTable printf("Buf is: '%.*s'\n", cast(int)(pend - start), buf.data + start); } // limit recursive expansion - __gshared int nest; - if (nest > global.recursionLimit) - { - error(Loc.initial, "DDoc macro expansion limit exceeded; more than %d expansions.", - global.recursionLimit); - return; - } - nest++; + recursionLimit--; + if (recursionLimit < 0) + return false; + size_t end = pend; assert(start <= end); assert(end <= buf.length); @@ -105,7 +101,9 @@ extern (C++) struct MacroTable end += marg.length - 2; // Scan replaced text for further expansion size_t mend = u + marg.length; - expand(buf, u, mend, null); + const success = expand(buf, u, mend, null, recursionLimit); + if (!success) + return false; end += mend - (u + marg.length); u = mend; } @@ -121,7 +119,9 @@ extern (C++) struct MacroTable end += -2 + 2 + marg.length + 2; // Scan replaced text for further expansion size_t mend = u + 2 + marg.length; - expand(buf, u + 2, mend, null); + const success = expand(buf, u + 2, mend, null, recursionLimit); + if (!success) + return false; end += mend - (u + 2 + marg.length); u = mend; } @@ -228,7 +228,9 @@ extern (C++) struct MacroTable // Scan replaced text for further expansion m.inuse++; size_t mend = v + 1 + 2 + m.text.length + 2; - expand(buf, v + 1, mend, marg); + const success = expand(buf, v + 1, mend, marg, recursionLimit); + if (!success) + return false; end += mend - (v + 1 + 2 + m.text.length + 2); m.inuse--; buf.remove(u, v + 1 - u); @@ -253,12 +255,12 @@ extern (C++) struct MacroTable } mem.xfree(cast(char*)arg); pend = end; - nest--; + return true; } private: - extern (D) Macro* search(const(char)[] name) + extern (D) Macro* search(const(char)[] name) @nogc nothrow pure @safe { //printf("Macro::search(%.*s)\n", cast(int)name.length, name.ptr); if (auto table = name in mactab) @@ -282,7 +284,7 @@ struct Macro const(char)[] text; // macro replacement text int inuse; // macro is in use (don't expand) - this(const(char)[] name, const(char)[] text) + this(const(char)[] name, const(char)[] text) @nogc nothrow pure @safe { this.name = name; this.text = text; @@ -297,7 +299,7 @@ struct Macro * copy allocated with mem.xmalloc() */ -char[] memdup(const(char)[] p) +char[] memdup(const(char)[] p) nothrow pure @trusted { size_t len = p.length; return (cast(char*)memcpy(mem.xmalloc(len), p.ptr, len))[0 .. len]; @@ -312,7 +314,7 @@ char[] memdup(const(char)[] p) * 1..9: get nth argument * -1: get 2nd through end */ -size_t extractArgN(const(char)[] buf, out const(char)[] marg, int n) +size_t extractArgN(const(char)[] buf, out const(char)[] marg, int n) @nogc nothrow pure { /* Scan forward for matching right parenthesis. * Nest parentheses. diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 5e802da..2cb1cc7 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -325,7 +325,6 @@ extern (C++) final class Module : Package extern (C++) __gshared Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them extern (C++) __gshared Dsymbols deferred2; // deferred Dsymbol's needing semantic2() run on them extern (C++) __gshared Dsymbols deferred3; // deferred Dsymbol's needing semantic3() run on them - extern (C++) __gshared uint dprogress; // progress resolving the deferred list static void _init() { @@ -1300,19 +1299,22 @@ extern (C++) final class Module : Package extern (D) static void addDeferredSemantic(Dsymbol s) { //printf("Module::addDeferredSemantic('%s')\n", s.toChars()); - deferred.push(s); + if (!deferred.contains(s)) + deferred.push(s); } extern (D) static void addDeferredSemantic2(Dsymbol s) { //printf("Module::addDeferredSemantic2('%s')\n", s.toChars()); - deferred2.push(s); + if (!deferred2.contains(s)) + deferred2.push(s); } extern (D) static void addDeferredSemantic3(Dsymbol s) { //printf("Module::addDeferredSemantic3('%s')\n", s.toChars()); - deferred3.push(s); + if (!deferred.contains(s)) + deferred3.push(s); } /****************************************** @@ -1320,19 +1322,15 @@ extern (C++) final class Module : Package */ static void runDeferredSemantic() { - if (dprogress == 0) - return; - __gshared int nested; if (nested) return; - //if (deferred.dim) printf("+Module::runDeferredSemantic(), len = %d\n", deferred.dim); + //if (deferred.dim) printf("+Module::runDeferredSemantic(), len = %ld\n", deferred.dim); nested++; size_t len; do { - dprogress = 0; len = deferred.dim; if (!len) break; @@ -1358,13 +1356,13 @@ extern (C++) final class Module : Package s.dsymbolSemantic(null); //printf("deferred: %s, parent = %s\n", s.toChars(), s.parent.toChars()); } - //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); + //printf("\tdeferred.dim = %ld, len = %ld\n", deferred.dim, len); if (todoalloc) free(todoalloc); } - while (deferred.dim < len || dprogress); // while making progress + while (deferred.dim != len); // while making progress nested--; - //printf("-Module::runDeferredSemantic(), len = %d\n", deferred.dim); + //printf("-Module::runDeferredSemantic(), len = %ld\n", deferred.dim); } static void runDeferredSemantic2() diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d index 6eb433e..ba83649 100644 --- a/gcc/d/dmd/doc.d +++ b/gcc/d/dmd/doc.d @@ -226,12 +226,12 @@ private final class ParamSection : Section buf.writestring("$(DDOC_PARAM_ID "); { size_t o = buf.length; - Parameter fparam = isFunctionParameter(a, namestart, namelen); + Parameter fparam = isFunctionParameter(a, namestart[0 .. namelen]); if (!fparam) { // Comments on a template might refer to function parameters within. // Search the parameters of nested eponymous functions (with the same name.) - fparam = isEponymousFunctionParameter(a, namestart, namelen); + fparam = isEponymousFunctionParameter(a, namestart[0 .. namelen]); } bool isCVariadic = isCVariadicParameter(a, namestart[0 .. namelen]); if (isCVariadic) @@ -328,7 +328,7 @@ private final class MacroSection : Section private alias Sections = Array!(Section); // Workaround for missing Parameter instance for variadic params. (it's unnecessary to instantiate one). -private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) +private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) @safe { foreach (member; *a) { @@ -339,7 +339,7 @@ private bool isCVariadicParameter(Dsymbols* a, const(char)[] p) return false; } -private Dsymbol getEponymousMember(TemplateDeclaration td) +private Dsymbol getEponymousMember(TemplateDeclaration td) @safe { if (!td.onemember) return null; @@ -456,7 +456,11 @@ extern(C++) void gendocfile(Module m) OutBuffer buf2; buf2.writestring("$(DDOC)"); size_t end = buf2.length; - m.macrotable.expand(buf2, 0, end, null); + + const success = m.macrotable.expand(buf2, 0, end, null, global.recursionLimit); + if (!success) + error(Loc.initial, "DDoc macro expansion limit exceeded; more than %d expansions.", global.recursionLimit); + version (all) { /* Remove all the escape sequences from buf2, @@ -2561,17 +2565,17 @@ private size_t replaceMarkdownEmphasis(ref OutBuffer buf, const ref Loc loc, ref /**************************************************** */ -private bool isIdentifier(Dsymbols* a, const(char)* p, size_t len) +private bool isIdentifier(Dsymbols* a, const(char)[] s) { foreach (member; *a) { if (auto imp = member.isImport()) { // For example: `public import str = core.stdc.string;` - // This checks if `p` is equal to `str` + // This checks if `s` is equal to `str` if (imp.aliasId) { - if (p[0 .. len] == imp.aliasId.toString()) + if (s == imp.aliasId.toString()) return true; } else @@ -2586,14 +2590,14 @@ private bool isIdentifier(Dsymbols* a, const(char)* p, size_t len) } fullyQualifiedImport ~= imp.id.toString(); - // Check if `p` == `core.stdc.string` - if (p[0 .. len] == fullyQualifiedImport) + // Check if `s` == `core.stdc.string` + if (s == fullyQualifiedImport) return true; } } else if (member.ident) { - if (p[0 .. len] == member.ident.toString()) + if (s == member.ident.toString()) return true; } @@ -2603,12 +2607,12 @@ private bool isIdentifier(Dsymbols* a, const(char)* p, size_t len) /**************************************************** */ -private bool isKeyword(const(char)* p, size_t len) +private bool isKeyword(const(char)[] str) @safe { immutable string[3] table = ["true", "false", "null"]; foreach (s; table) { - if (p[0 .. len] == s) + if (str == s) return true; } return false; @@ -2616,7 +2620,7 @@ private bool isKeyword(const(char)* p, size_t len) /**************************************************** */ -private TypeFunction isTypeFunction(Dsymbol s) +private TypeFunction isTypeFunction(Dsymbol s) @safe { FuncDeclaration f = s.isFuncDeclaration(); /* f.type may be NULL for template members. @@ -2632,14 +2636,14 @@ private TypeFunction isTypeFunction(Dsymbol s) /**************************************************** */ -private Parameter isFunctionParameter(Dsymbol s, const(char)* p, size_t len) +private Parameter isFunctionParameter(Dsymbol s, const(char)[] str) @safe { TypeFunction tf = isTypeFunction(s); if (tf && tf.parameterList.parameters) { foreach (fparam; *tf.parameterList.parameters) { - if (fparam.ident && p[0 .. len] == fparam.ident.toString()) + if (fparam.ident && str == fparam.ident.toString()) { return fparam; } @@ -2650,11 +2654,11 @@ private Parameter isFunctionParameter(Dsymbol s, const(char)* p, size_t len) /**************************************************** */ -private Parameter isFunctionParameter(Dsymbols* a, const(char)* p, size_t len) +private Parameter isFunctionParameter(Dsymbols* a, const(char)[] p) @safe { - for (size_t i = 0; i < a.dim; i++) + foreach (Dsymbol sym; *a) { - Parameter fparam = isFunctionParameter((*a)[i], p, len); + Parameter fparam = isFunctionParameter(sym, p); if (fparam) { return fparam; @@ -2665,11 +2669,11 @@ private Parameter isFunctionParameter(Dsymbols* a, const(char)* p, size_t len) /**************************************************** */ -private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char) *p, size_t len) +private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char)[] p) @safe { - for (size_t i = 0; i < a.dim; i++) + foreach (Dsymbol dsym; *a) { - TemplateDeclaration td = (*a)[i].isTemplateDeclaration(); + TemplateDeclaration td = dsym.isTemplateDeclaration(); if (td && td.onemember) { /* Case 1: we refer to a template declaration inside the template @@ -2688,7 +2692,7 @@ private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char) *p, size /// ...ddoc... alias case2 = case1!int; */ - AliasDeclaration ad = (*a)[i].isAliasDeclaration(); + AliasDeclaration ad = dsym.isAliasDeclaration(); if (ad && ad.aliassym) { td = ad.aliassym.isTemplateDeclaration(); @@ -2699,7 +2703,7 @@ private Parameter isEponymousFunctionParameter(Dsymbols *a, const(char) *p, size Dsymbol sym = getEponymousMember(td); if (sym) { - Parameter fparam = isFunctionParameter(sym, p, len); + Parameter fparam = isFunctionParameter(sym, p); if (fparam) { return fparam; @@ -4956,17 +4960,17 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s i = buf.bracket(i, "$(DDOC_AUTO_PSYMBOL_SUPPRESS ", j - 1, ")") - 1; break; } - if (isIdentifier(a, start, len)) + if (isIdentifier(a, start[0 .. len])) { i = buf.bracket(i, "$(DDOC_AUTO_PSYMBOL ", j, ")") - 1; break; } - if (isKeyword(start, len)) + if (isKeyword(start[0 .. len])) { i = buf.bracket(i, "$(DDOC_AUTO_KEYWORD ", j, ")") - 1; break; } - if (isFunctionParameter(a, start, len)) + if (isFunctionParameter(a, start[0 .. len])) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg.ident.toChars(), i, j); i = buf.bracket(i, "$(DDOC_AUTO_PARAM ", j, ")") - 1; @@ -5055,7 +5059,7 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off if (i < j) { size_t len = j - i; - if (isIdentifier(a, start, len)) + if (isIdentifier(a, start[0 .. len])) { i = buf.bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; continue; @@ -5066,12 +5070,12 @@ private void highlightCode(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t off if (i < j) { size_t len = j - i; - if (isIdentifier(a, start, len)) + if (isIdentifier(a, start[0 .. len])) { i = buf.bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; continue; } - if (isFunctionParameter(a, start, len)) + if (isFunctionParameter(a, start[0 .. len])) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg.ident.toChars(), i, j); i = buf.bracket(i, "$(DDOC_PARAM ", j, ")") - 1; @@ -5195,12 +5199,12 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of if (!sc) break; size_t len = lex.p - tok.ptr; - if (isIdentifier(a, tok.ptr, len)) + if (isIdentifier(a, tok.ptr[0 .. len])) { highlight = "$(D_PSYMBOL "; break; } - if (isFunctionParameter(a, tok.ptr, len)) + if (isFunctionParameter(a, tok.ptr[0 .. len])) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg.ident.toChars(), i, j); highlight = "$(D_PARAM "; @@ -5246,7 +5250,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of /**************************************** * Determine if p points to the start of a "..." parameter identifier. */ -private bool isCVariadicArg(const(char)[] p) +private bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe { return p.length >= 3 && p[0 .. 3] == "..."; } @@ -5254,7 +5258,7 @@ private bool isCVariadicArg(const(char)[] p) /**************************************** * Determine if p points to the start of an identifier. */ -bool isIdStart(const(char)* p) +bool isIdStart(const(char)* p) @nogc nothrow pure { dchar c = *p; if (isalpha(c) || c == '_') @@ -5273,7 +5277,7 @@ bool isIdStart(const(char)* p) /**************************************** * Determine if p points to the rest of an identifier. */ -bool isIdTail(const(char)* p) +bool isIdTail(const(char)* p) @nogc nothrow pure { dchar c = *p; if (isalnum(c) || c == '_') @@ -5292,7 +5296,7 @@ bool isIdTail(const(char)* p) /**************************************** * Determine if p points to the indentation space. */ -private bool isIndentWS(const(char)* p) +private bool isIndentWS(const(char)* p) @nogc nothrow pure @safe { return (*p == ' ') || (*p == '\t'); } @@ -5300,7 +5304,7 @@ private bool isIndentWS(const(char)* p) /***************************************** * Return number of bytes in UTF character. */ -int utfStride(const(char)* p) +int utfStride(const(char)* p) @nogc nothrow pure { dchar c = *p; if (c < 0x80) @@ -5310,7 +5314,7 @@ int utfStride(const(char)* p) return cast(int)i; } -private inout(char)* stripLeadingNewlines(inout(char)* s) +private inout(char)* stripLeadingNewlines(inout(char)* s) @nogc nothrow pure { while (s && *s == '\n' || *s == '\r') s++; diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 7f57cbe..c3424dc 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -359,6 +359,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor dsym.overlapped = true; dsym.sequenceNumber = global.varSequenceNumber++; + if (!dsym.isScope()) + dsym.maybeScope = true; Scope* scx = null; if (dsym._scope) @@ -2034,8 +2036,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor ed.semanticRun = PASS.semanticdone; return; } - uint dprogress_save = Module.dprogress; - Scope* scx = null; if (ed._scope) { @@ -2093,7 +2093,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { // memtype is forward referenced, so try again later deferDsymbolSemantic(ed, scx); - Module.dprogress = dprogress_save; //printf("\tdeferring %s\n", toChars()); ed.semanticRun = PASS.initial; return; @@ -2134,8 +2133,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!(sc.flags & SCOPE.Cfile)) // C enum remains incomplete until members are done ed.semanticRun = PASS.semanticdone; - Module.dprogress++; - // @@@DEPRECATED_2.110@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint // Deprecated in 2.100 // Make an error in 2.110 @@ -3945,7 +3942,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (funcdecl.canInferAttributes(sc)) funcdecl.initInferAttributes(); - Module.dprogress++; funcdecl.semanticRun = PASS.semanticdone; /* Save scope for possible later use (if we need the @@ -4669,7 +4665,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor sd.inv = buildInv(sd, sc2); - Module.dprogress++; sd.semanticRun = PASS.semanticdone; //printf("-StructDeclaration::semantic(this=%p, '%s')\n", sd, sd.toChars()); @@ -5329,7 +5324,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor cldec.inv = buildInv(cldec, sc2); - Module.dprogress++; cldec.semanticRun = PASS.semanticdone; //printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type); @@ -5676,7 +5670,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor idec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) ); - Module.dprogress++; idec.semanticRun = PASS.semanticdone; //printf("-InterfaceDeclaration.dsymbolSemantic(%s), type = %p\n", toChars(), type); @@ -6332,6 +6325,10 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* * resolve the alias of eponymous member. */ tempinst.aliasdecl = tempinst.aliasdecl.toAlias2(); + + // stop AliasAssign tuple building + if (auto td = tempinst.aliasdecl.isTupleDeclaration()) + td.building = false; } Laftersemantic: @@ -6726,13 +6723,28 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) */ const errors = global.errors; + Dsymbol s; + + // Try AliasSeq optimization + if (auto ti = ds.type.isTypeInstance()) + { + if (!ti.tempinst.findTempDecl(sc, null)) + return errorRet(); + if (auto tempinst = isAliasSeq(sc, ti)) + { + s = aliasAssignInPlace(sc, tempinst, aliassym); + if (!s) + return errorRet(); + goto Lsymdone; + } + } /* This section is needed because Type.resolve() will: * const x = 3; * alias y = x; * try to convert identifier x to 3. */ - auto s = ds.type.toDsymbol(sc); + s = ds.type.toDsymbol(sc); if (errors != global.errors) return errorRet(); if (s == aliassym) @@ -6784,6 +6796,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) if (s) // it's a symbolic alias { + Lsymdone: //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars()); aliassym.type = null; aliassym.aliassym = s; @@ -6813,6 +6826,135 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) } /*************************************** + * Expands template instance arguments inside 'alias assign' target declaration (aliassym), + * instead of inside 'tempinst.tiargs' every time. + * Params: + * tempinst = AliasSeq instance + * aliassym = the AliasDeclaration corresponding to AliasAssign + * Returns: + * null. + */ +private TupleDeclaration aliasAssignInPlace(Scope* sc, TemplateInstance tempinst, + AliasDeclaration aliassym) +{ + // Mark instance with semantic done, not needed but just in case. + tempinst.inst = tempinst; + tempinst.semanticRun = PASS.semanticdone; + TupleDeclaration td; + if (aliassym.type) + { + // Convert TypeTuple to TupleDeclaration to avoid back and forth allocations + // in the assignment process + if (auto tt = aliassym.type.isTypeTuple()) + { + auto objs = new Objects(tt.arguments.length); + foreach (i, p; *tt.arguments) + (*objs)[i] = p.type; + td = new TupleDeclaration(tempinst.loc, aliassym.ident, objs); + td.storage_class |= STC.templateparameter; + td.building = true; + aliassym.type = null; + } + else if (aliassym.type.isTypeError()) + return null; + + } + else if (auto otd = aliassym.aliassym.isTupleDeclaration()) + { + if (otd.building) + td = otd; + else + { + td = new TupleDeclaration(tempinst.loc, aliassym.ident, otd.objects.copy()); + td.storage_class |= STC.templateparameter; + td.building = true; + } + } + // If starting from single element in aliassym (td == null) we need to build the tuple + // after semanticTiargs to keep same semantics (for example a FuncLiteraldeclaration + // template argument is converted to FuncExp) + if (td) + aliassym.aliassym = td; + aliassym.semanticRun = PASS.semanticdone; + if (!TemplateInstance.semanticTiargs(tempinst.loc, sc, tempinst.tiargs, 0, td)) + { + tempinst.errors = true; + return null; + } + // The alias will stop tuple 'building' mode when used (in AliasDeclaration.toAlias(), + // then TupleDeclaration.getType() will work again) + aliassym.semanticRun = PASS.initial; + if (!td) + { + td = new TupleDeclaration(tempinst.loc, aliassym.ident, tempinst.tiargs); + td.storage_class |= STC.templateparameter; + td.building = true; + return td; + } + + auto tiargs = tempinst.tiargs; + size_t oldlen = td.objects.length; + size_t origstart; + size_t insertidx; + size_t insertlen; + foreach (i, o; *tiargs) + { + if (o !is td) + { + ++insertlen; + continue; + } + // tuple contains itself (tuple = AliasSeq!(..., tuple, ...)) + if (insertlen) // insert any left element before + { + td.objects.insert(insertidx, (*tiargs)[i - insertlen .. i]); + if (insertidx == 0) // reset original tuple start point + origstart = insertlen; + insertlen = 0; + } + if (insertidx) // insert tuple if found more than one time + { + td.objects.reserve(oldlen); // reserve first to assert a valid slice + td.objects.pushSlice((*td.objects)[origstart .. origstart + oldlen]); + } + insertidx = td.objects.length; + } + if (insertlen) + { + if (insertlen != tiargs.length) // insert any left element + td.objects.pushSlice((*tiargs)[$ - insertlen .. $]); + else + // just assign tiargs if tuple = AliasSeq!(nottuple, nottuple...) + td.objects = tempinst.tiargs; + } + return td; +} + +/*************************************** + * Check if a template instance is a trivial AliasSeq but without other overloads. + * We can only be 100% sure of being AliasSeq after running semanticTiargs() + * and findBestMatch() but this optimization must happen before that. + */ +private TemplateInstance isAliasSeq(Scope* sc, TypeInstance ti) +{ + auto tovers = ti.tempinst.tempdecl.isOverloadSet(); + foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1) + { + Dsymbol dstart = tovers ? tovers.a[oi] : ti.tempinst.tempdecl; + int r = overloadApply(dstart, (Dsymbol s) + { + auto td = s.isTemplateDeclaration(); + if (!td || !td.isTrivialAliasSeq) + return 1; + return 0; + }); + if (r) + return null; + } + return ti.tempinst; +} + +/*************************************** * Find all instance fields in `ad`, then push them into `fields`. * * Runs semantic() for all instance field variables, but also diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 02f12e4..34cae1d 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -6564,10 +6564,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol * tiargs array of template arguments * flags 1: replace const variables with their initializers * 2: don't devolve Parameter to Type + * atd tuple being optimized. If found, it's not expanded here + * but in AliasAssign semantic. * Returns: * false if one or more arguments have errors. */ - extern (D) static bool semanticTiargs(const ref Loc loc, Scope* sc, Objects* tiargs, int flags) + extern (D) static bool semanticTiargs(const ref Loc loc, Scope* sc, Objects* tiargs, int flags, TupleDeclaration atd = null) { // Run semantic on each argument, place results in tiargs[] //printf("+TemplateInstance.semanticTiargs()\n"); @@ -6767,6 +6769,11 @@ extern (C++) class TemplateInstance : ScopeDsymbol TupleDeclaration d = sa.toAlias().isTupleDeclaration(); if (d) { + if (d is atd) + { + (*tiargs)[j] = d; + continue; + } // Expand tuple tiargs.remove(j); tiargs.insert(j, d.objects); diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index fb5e092..4f06bac 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -36,6 +36,21 @@ import dmd.tokens; import dmd.visitor; import dmd.arraytypes; +/// Groups global state for escape checking together +package(dmd) struct EscapeState +{ + // Maps `sequenceNumber` of a `VarDeclaration` to an object that contains the + // reason it failed to infer `scope` + // https://issues.dlang.org/show_bug.cgi?id=23295 + private __gshared RootObject[int] scopeInferFailure; + + /// Called by `initDMD` / `deinitializeDMD` to reset global state + static void reset() + { + scopeInferFailure = null; + } +} + /****************************************************** * Checks memory objects passed to a function. * Checks that if a memory object is passed by ref or by pointer, @@ -271,6 +286,40 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag) return errors; } +/** + * A `scope` variable was assigned to non-scope parameter `v`. + * If applicable, print why the parameter was not inferred `scope`. + * + * Params: + * printFunc = error/deprecation print function to use + * v = parameter that was not inferred + * recursionLimit = recursion limit for printing the reason + */ +void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit) +{ + recursionLimit--; + if (recursionLimit < 0 || !v) + return; + + if (RootObject* o = v.sequenceNumber in EscapeState.scopeInferFailure) + { + switch ((*o).dyncast()) + { + case DYNCAST.expression: + Expression e = cast(Expression) *o; + printFunc(e.loc, "which is not `scope` because of `%s`", e.toChars()); + break; + case DYNCAST.dsymbol: + VarDeclaration v1 = cast(VarDeclaration) *o; + printFunc(v1.loc, "which is assigned to non-scope parameter `%s`", v1.toChars()); + printScopeFailure(printFunc, v1, recursionLimit); + break; + default: + assert(0); + } + } +} + /**************************************** * Function parameter `par` is being initialized to `arg`, * and `par` may escape. @@ -280,6 +329,7 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag) * sc = used to determine current function and module * fdc = function being called, `null` if called indirectly * par = function parameter (`this` if null) + * vPar = `VarDeclaration` corresponding to `par` * parStc = storage classes of function parameter (may have added `scope` from `pure`) * arg = initializer for param * assertmsg = true if the parameter is the msg argument to assert(bool, msg). @@ -287,7 +337,7 @@ bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag) * Returns: * `true` if pointers to the stack can escape via assignment */ -bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC parStc, Expression arg, bool assertmsg, bool gag) +bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag) { enum log = false; if (log) printf("checkParamArgumentEscape(arg: %s par: %s)\n", @@ -327,13 +377,21 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC } else if (par) { - result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`", v, par, fdc); + if (sc.setUnsafeDIP1000(gag, arg.loc, + desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`", v, par, fdc)) + { + result = true; + printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10); + } } else { - result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `this` calling `%s`", v, fdc); + if (sc.setUnsafeDIP1000(gag, arg.loc, + desc ~ " `%s` assigned to non-scope parameter `this` calling `%s`", v, fdc)) + { + result = true; + printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), fdc.vthis, 10); + } } } @@ -345,7 +403,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC Dsymbol p = v.toParent2(); - notMaybeScope(v); + notMaybeScope(v, vPar); if (v.isScope()) { @@ -366,7 +424,8 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC */ if (log) printf("no infer for %s in %s loc %s, fdc %s, %d\n", v.toChars(), sc.func.ident.toChars(), sc.func.loc.toChars(), fdc.ident.toChars(), __LINE__); - v.doNotInferScope = true; + + doNotInferScope(v, vPar); } } @@ -378,7 +437,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC Dsymbol p = v.toParent2(); - notMaybeScope(v); + notMaybeScope(v, arg); if (checkScopeVarAddr(v, arg, sc, gag)) { result = true; @@ -405,7 +464,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC Dsymbol p = v.toParent2(); - notMaybeScope(v); + notMaybeScope(v, arg); if ((v.isReference() || v.isScope()) && p == sc.func) { @@ -553,7 +612,16 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) return false; if (e1.isSliceExp()) - return false; + { + if (VarDeclaration va = expToVariable(e1)) + { + if (!va.type.toBasetype().isTypeSArray() || // treat static array slice same as a variable + !va.type.hasPointers()) + return false; + } + else + return false; + } /* The struct literal case can arise from the S(e2) constructor call: * return S(e2); @@ -650,7 +718,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (va && !vaIsRef && !va.isScope() && !v.isScope() && !v.isTypesafeVariadicParameter && !va.isTypesafeVariadicParameter && - (va.storage_class & v.storage_class & STC.maybescope) && + (va.isParameter() && va.maybeScope && v.isParameter() && v.maybeScope) && p == fd) { /* Add v to va's list of dependencies @@ -660,7 +728,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } if (vaIsFirstRef && - (v.isScope() || (v.storage_class & STC.maybescope)) && + (v.isScope() || v.maybeScope) && !(v.storage_class & STC.return_) && v.isParameter() && fd.flags & FUNCFLAG.returnInprocess && @@ -672,7 +740,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } if (!(va && va.isScope()) || vaIsRef) - notMaybeScope(v); + notMaybeScope(v, e); if (v.isScope()) { @@ -682,7 +750,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (va.isScope()) continue; - if (!va.doNotInferScope) + if (va.maybeScope) { if (log) printf("inferring scope for lvalue %s\n", va.toChars()); va.storage_class |= STC.scope_ | STC.scopeinferred; @@ -711,7 +779,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } } - if (va && !va.isDataseg() && !va.doNotInferScope) + if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) { if (!va.isScope()) { /* v is scope, and va is not scope, so va needs to @@ -742,7 +810,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) Type tb = v.type.toBasetype(); if (tb.ty == Tarray || tb.ty == Tsarray) { - if (va && !va.isDataseg() && !va.doNotInferScope) + if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) { if (!va.isScope()) { //printf("inferring scope for %s\n", va.toChars()); @@ -759,7 +827,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) * It may escape via that assignment, therefore, v can never be 'scope'. */ //printf("no infer for %s in %s, %d\n", v.toChars(), fd.ident.toChars(), __LINE__); - v.doNotInferScope = true; + doNotInferScope(v, e); } } @@ -812,12 +880,12 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } if (!(va && va.isScope())) - notMaybeScope(v); + notMaybeScope(v, e); if (p != sc.func) continue; - if (va && !va.isDataseg() && !va.doNotInferScope) + if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) { if (!va.isScope()) { //printf("inferring scope for %s\n", va.toChars()); @@ -855,12 +923,12 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) Dsymbol p = v.toParent2(); if (!(va && va.isScope())) - notMaybeScope(v); + notMaybeScope(v, e); if (!(v.isReference() || v.isScope()) || p != fd) continue; - if (va && !va.isDataseg() && !va.doNotInferScope) + if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) { /* Don't infer STC.scope_ for va, because then a closure * won't be generated for fd. @@ -891,7 +959,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } if (ee.op == EXP.call && ee.type.toBasetype().isTypeStruct() && - (!va || !(va.storage_class & STC.temp))) + (!va || !(va.storage_class & STC.temp) && !va.isScope())) { if (sc.setUnsafeDIP1000(gag, ee.loc, "address of struct temporary returned by `%s` assigned to longer lived variable `%s`", ee, e1)) { @@ -910,7 +978,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) } } - if (va && !va.isDataseg() && !va.doNotInferScope) + if (va && !va.isDataseg() && (va.isScope() || va.maybeScope)) { if (!va.isScope()) { //printf("inferring scope for %s\n", va.toChars()); @@ -963,8 +1031,7 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag) } else { - //printf("no infer for %s in %s, %d\n", v.toChars(), sc.func.ident.toChars(), __LINE__); - v.doNotInferScope = true; + notMaybeScope(v, new ThrowExp(e.loc, e)); } } return result; @@ -1036,7 +1103,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) else { //printf("no infer for %s in %s, %d\n", v.toChars(), sc.func.ident.toChars(), __LINE__); - v.doNotInferScope = true; + notMaybeScope(v, e); } } @@ -1191,7 +1258,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) Dsymbol p = v.toParent2(); - if ((v.isScope() || (v.storage_class & STC.maybescope)) && + if ((v.isScope() || v.maybeScope) && !(v.storage_class & STC.return_) && v.isParameter() && !v.doNotInferReturn && @@ -1266,7 +1333,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) else { //printf("no infer for %s in %s, %d\n", v.toChars(), sc.func.ident.toChars(), __LINE__); - v.doNotInferScope = true; + doNotInferScope(v, e); } } @@ -1330,7 +1397,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) if (!refs) { if (sc.func.vthis == v) - notMaybeScope(v); + notMaybeScope(v, e); if (checkScopeVarAddr(v, e, sc, gag)) { @@ -2226,26 +2293,41 @@ public void findAllOuterAccessedVariables(FuncDeclaration fd, VarDeclarations* v } /*********************************** - * Turn off `STC.maybescope` for variable `v`. + * Turn off `maybeScope` for variable `v`. * - * This exists in order to find where `STC.maybescope` is getting turned off. + * This exists in order to find where `maybeScope` is getting turned off. * Params: * v = variable + * o = reason for it being turned off: + * - `Expression` such as `throw e` or `&e` + * - `VarDeclaration` of a non-scope parameter it was assigned to + * - `null` for no reason */ -version (none) +private void notMaybeScope(VarDeclaration v, RootObject o) { - private void notMaybeScope(string file = __FILE__, int line = __LINE__)(VarDeclaration v) + if (v.maybeScope) { - printf("%.*s(%d): notMaybeScope('%s')\n", cast(int)file.length, file.ptr, line, v.toChars()); - v.storage_class &= ~STC.maybescope; + v.maybeScope = false; + if (o && v.isParameter()) + EscapeState.scopeInferFailure[v.sequenceNumber] = o; } } -else + +/*********************************** + * Turn off `maybeScope` for variable `v` if it's not a parameter. + * + * This is for compatibility with the old system with both `STC.maybescope` and `VarDeclaration.doNotInferScope`, + * which is now just `VarDeclaration.maybeScope`. + * This function should probably be removed in future refactors. + * + * Params: + * v = variable + * o = reason for it being turned off + */ +private void doNotInferScope(VarDeclaration v, RootObject o) { - private void notMaybeScope(VarDeclaration v) - { - v.storage_class &= ~STC.maybescope; - } + if (!v.isParameter) + notMaybeScope(v, o); } /*********************************** @@ -2259,6 +2341,7 @@ else */ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) { + if (funcdecl.flags & FUNCFLAG.returnInprocess) { funcdecl.flags &= ~FUNCFLAG.returnInprocess; @@ -2273,6 +2356,8 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) } } + if (!(funcdecl.flags & FUNCFLAG.inferScope)) + return; funcdecl.flags &= ~FUNCFLAG.inferScope; // Eliminate maybescope's @@ -2305,20 +2390,19 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) foreach (u, p; f.parameterList) { auto v = (*funcdecl.parameters)[u]; - if (v.storage_class & STC.maybescope) + if (v.maybeScope) { //printf("Inferring scope for %s\n", v.toChars()); - notMaybeScope(v); + notMaybeScope(v, null); v.storage_class |= STC.scope_ | STC.scopeinferred; p.storageClass |= STC.scope_ | STC.scopeinferred; - assert(!(p.storageClass & STC.maybescope)); } } } - if (funcdecl.vthis && funcdecl.vthis.storage_class & STC.maybescope) + if (funcdecl.vthis && funcdecl.vthis.maybeScope) { - notMaybeScope(funcdecl.vthis); + notMaybeScope(funcdecl.vthis, null); funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred; f.isScopeQual = true; f.isscopeinferred = true; @@ -2358,17 +2442,17 @@ private void eliminateMaybeScopes(VarDeclaration[] array) foreach (va; array) { if (log) printf(" va = %s\n", va.toChars()); - if (!(va.storage_class & (STC.maybescope | STC.scope_))) + if (!(va.maybeScope || va.isScope())) { if (va.maybes) { foreach (v; *va.maybes) { if (log) printf(" v = %s\n", v.toChars()); - if (v.storage_class & STC.maybescope) + if (v.maybeScope) { // v cannot be scope since it is assigned to a non-scope va - notMaybeScope(v); + notMaybeScope(v, va); if (!v.isReference()) v.storage_class &= ~(STC.return_ | STC.returninferred); changes = true; @@ -2485,7 +2569,7 @@ private bool enclosesLifetimeOf(const VarDeclaration va, const VarDeclaration v) * analysis for the function is completed. Thus, we save the data * until then. * Params: - * v = an `STC.maybescope` variable that was assigned to `this` + * v = a variable with `maybeScope == true` that was assigned to `this` */ private void addMaybe(VarDeclaration va, VarDeclaration v) { @@ -2570,8 +2654,7 @@ private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool g if (!v.isScope()) { - v.storage_class &= ~STC.maybescope; - v.doNotInferScope = true; + notMaybeScope(v, e); return false; } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 397a41b..f871fade 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -5153,7 +5153,7 @@ extern (C++) final class CallExp : UnaExp /* Type needs destruction, so declare a tmp * which the back end will recognize and call dtor on */ - auto tmp = copyToTemp(0, "__tmpfordtor", this); + auto tmp = copyToTemp(0, Id.__tmpfordtor.toString(), this); auto de = new DeclarationExp(loc, tmp); auto ve = new VarExp(loc, tmp); Expression e = new CommaExp(loc, de, ve); diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 30baabd..3114100 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -2044,7 +2044,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* Argument value can escape from the called function. * Check arg to see if it matters. */ - err |= checkParamArgumentEscape(sc, fd, p, cast(STC) pStc, arg, false, false); + VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null; + err |= checkParamArgumentEscape(sc, fd, p, vPar, cast(STC) pStc, arg, false, false); } // Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference @@ -4726,7 +4727,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tthis = ue.e1.type; if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual)) { - if (checkParamArgumentEscape(sc, exp.f, null, STC.undefined_, ethis, false, false)) + if (checkParamArgumentEscape(sc, exp.f, null, null, STC.undefined_, ethis, false, false)) return setError(); } } @@ -6388,7 +6389,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.msg = resolveProperties(sc, exp.msg); exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf()); exp.msg = exp.msg.optimize(WANTvalue); - checkParamArgumentEscape(sc, null, null, STC.undefined_, exp.msg, true, false); + checkParamArgumentEscape(sc, null, null, null, STC.undefined_, exp.msg, true, false); } if (exp.msg && exp.msg.op == EXP.error) @@ -9934,7 +9935,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (isArrayCtor || isArraySetCtor) { const ts = t1b.nextOf().baseElemOf().isTypeStruct(); - if (!ts || (!ts.sym.postblit && !ts.sym.dtor)) + if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor)) return setResult(res); auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor; @@ -9976,10 +9977,89 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor message("lowered %s =>\n %s", exp.toChars(), res.toChars()); } } + else if (auto ae = res.isAssignExp()) + res = lowerArrayAssign(ae); + else if (auto ce = res.isCommaExp()) + { + if (auto ae1 = ce.e1.isAssignExp()) + ce.e1 = lowerArrayAssign(ae1, true); + if (auto ae2 = ce.e2.isAssignExp()) + ce.e2 = lowerArrayAssign(ae2, true); + } return setResult(res); } + /*************************************** + * Lower AssignExp to `_d_arrayassign_{l,r}` if needed. + * + * Params: + * ae = the AssignExp to be lowered + * fromCommaExp = indicates whether `ae` is part of a CommaExp or not, + * so no unnecessary temporay variable is created. + * Returns: + * a CommaExp contiaining call a to `_d_arrayassign_{l,r}` if needed or + * `ae` otherwise + */ + private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false) + { + Type t1b = ae.e1.type.toBasetype(); + if (t1b.ty != Tsarray && t1b.ty != Tarray) + return ae; + + const isArrayAssign = + (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) && + (ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) && + (ae.e1.type.nextOf && ae.e2.type.nextOf && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf)); + + if (!isArrayAssign) + return ae; + + const ts = t1b.nextOf().baseElemOf().isTypeStruct(); + if (!ts || (!ts.sym.postblit && !ts.sym.dtor)) + return ae; + + Expression res; + auto func = ae.e2.isLvalue || ae.e2.isSliceExp ? Id._d_arrayassign_l : Id._d_arrayassign_r; + + // Lower to `.object._d_arrayassign_l{r}(e1, e2)`` + Expression id = new IdentifierExp(ae.loc, Id.empty); + id = new DotIdExp(ae.loc, id, Id.object); + id = new DotIdExp(ae.loc, id, func); + + auto arguments = new Expressions(); + arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf) + .expressionSemantic(sc)); + + Expression eValue2, value2 = ae.e2; + if (ae.e2.isLvalue) + value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf) + .expressionSemantic(sc); + else if (!fromCommaExp) + { + // Rvalues from CommaExps were introduced in `visit(AssignExp)` + // and are temporary variables themselves. Rvalues from trivial + // SliceExps are simply passed by reference without any copying. + + // `__assigntmp` will be destroyed together with the array `ae.e1`. + // When `ae.e2` is a variadic arg array, it is also `scope`, so + // `__assigntmp` may also be scope. + auto vd = copyToTemp(STC.rvalue | STC.nodtor | STC.scope_, "__assigntmp", ae.e2); + eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc); + value2 = new VarExp(vd.loc, vd).expressionSemantic(sc); + } + arguments.push(value2); + + Expression ce = new CallExp(ae.loc, id, arguments); + res = Expression.combine(eValue2, ce).expressionSemantic(sc); + res = Expression.combine(res, ae.e1).expressionSemantic(sc); + + if (global.params.verbose) + message("lowered %s =>\n %s", ae.toChars(), res.toChars()); + + return res; + } + override void visit(PowAssignExp exp) { if (exp.type) @@ -13092,7 +13172,10 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) if (sc.func && sc.func.isSynchronized()) return false; - return sharedError(e); + if (!allowRef && e.type.isShared()) + return sharedError(e); + + return false; } bool visitDotVar(DotVarExp e) @@ -13182,8 +13265,6 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) } if (sc.func && !sc.intypeof && !v.isDataseg()) { - v.storage_class &= ~STC.maybescope; - v.doNotInferScope = true; if (global.params.useDIP1000 != FeatureState.enabled && !(v.storage_class & STC.temp) && sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func)) diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 7475cb4..4c09474 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -568,8 +568,6 @@ extern (C++) class FuncDeclaration : Declaration if (tf.isreturnscope) vthis.storage_class |= STC.returnScope; } - if (flags & FUNCFLAG.inferScope && !(vthis.storage_class & STC.scope_)) - vthis.storage_class |= STC.maybescope; vthis.dsymbolSemantic(sc); if (!sc.insert(vthis)) diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index 05886f9..745d5eb 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -116,10 +116,6 @@ extern (C++) struct Param DiagnosticReporting useDeprecated = DiagnosticReporting.inform; // how use of deprecated features are handled bool useUnitTests; // generate unittest code bool useInline = false; // inline expand functions - FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 - FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params - bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070 - bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md bool release; // build release version bool preservePaths; // true means don't strip path from source file DiagnosticReporting warnings = DiagnosticReporting.off; // how compiler warnings are handled @@ -131,31 +127,10 @@ extern (C++) struct Param bool useModuleInfo = true; // generate runtime module information bool useTypeInfo = true; // generate runtime type information bool useExceptions = true; // support exception handling - bool noSharedAccess; // read/write access to shared memory objects - bool previewIn; // `in` means `[ref] scope const`, accepts rvalues - bool shortenedMethods; // allow => in normal function declarations bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations - bool fix16997 = true; // fix integral promotions for unary + - ~ operators - // https://issues.dlang.org/show_bug.cgi?id=16997 - bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes - bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract - /** The --transition=safe switch should only be used to show code with - * silent semantics changes related to @safe improvements. It should not be - * used to hide a feature that will have to go through deprecate-then-error - * before becoming default. - */ - bool ehnogc; // use @nogc exception handling - FeatureState dtorFields; // destruct fields of partially constructed objects - // https://issues.dlang.org/show_bug.cgi?id=14246 - bool fieldwise; // do struct equality testing field-wise rather than by memcmp() bool bitfields; // support C style bit fields - FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters - // https://dconf.org/2019/talks/alexandrescu.html - // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a - // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html - // Implementation: https://github.com/dlang/dmd/pull/9817 CppStdRevision cplusplus = CppStdRevision.cpp11; // version of C++ standard to support @@ -173,6 +148,28 @@ extern (C++) struct Param bool hcUsage; // print help on -HC switch bool logo; // print compiler logo + // Options for `-preview=/-revert=` + FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 + FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params + bool ehnogc; // use @nogc exception handling + bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md + bool fieldwise; // do struct equality testing field-wise rather than by memcmp() + bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes + FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters + // https://dconf.org/2019/talks/alexandrescu.html + // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a + // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html + // Implementation: https://github.com/dlang/dmd/pull/9817 + bool noSharedAccess; // read/write access to shared memory objects + bool previewIn; // `in` means `[ref] scope const`, accepts rvalues + bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract + bool shortenedMethods; // allow => in normal function declarations + bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070 + bool fix16997 = true; // fix integral promotions for unary + - ~ operators + // https://issues.dlang.org/show_bug.cgi?id=16997 + FeatureState dtorFields; // destruct fields of partially constructed objects + // https://issues.dlang.org/show_bug.cgi?id=14246 + CHECKENABLE useInvariants = CHECKENABLE._default; // generate class invariant checks CHECKENABLE useIn = CHECKENABLE._default; // generate precondition checks CHECKENABLE useOut = CHECKENABLE._default; // generate postcondition checks diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index 41472b2..a6b1c90 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -116,10 +116,6 @@ struct Param Diagnostic useDeprecated; bool useUnitTests; // generate unittest code bool useInline; // inline expand functions - FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 - FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params - bool fixImmutableConv; - bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md bool release; // build release version bool preservePaths; // true means don't strip path from source file Diagnostic warnings; @@ -131,22 +127,10 @@ struct Param bool useModuleInfo; // generate runtime module information bool useTypeInfo; // generate runtime type information bool useExceptions; // support exception handling - bool noSharedAccess; // read/write access to shared memory objects - bool previewIn; // `in` means `scope const`, perhaps `ref`, accepts rvalues - bool shortenedMethods; // allow => in normal function declarations bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations - bool fix16997; // fix integral promotions for unary + - ~ operators - // https://issues.dlang.org/show_bug.cgi?id=16997 - bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes - bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract - bool ehnogc; // use @nogc exception handling - FeatureState dtorFields; // destruct fields of partially constructed objects - // https://issues.dlang.org/show_bug.cgi?id=14246 - bool fieldwise; // do struct equality testing field-wise rather than by memcmp() bool bitfields; // support C style bit fields - FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters CppStdRevision cplusplus; // version of C++ name mangling to support bool showGaggedErrors; // print gagged errors anyway bool printErrorContext; // print errors with the error context (the error line in the source file) @@ -162,6 +146,27 @@ struct Param bool hcUsage; // print help on -HC switch bool logo; // print logo; + // Options for `-preview=/-revert=` + FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 + FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params + bool ehnogc; // use @nogc exception handling + bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md + bool fieldwise; // do struct equality testing field-wise rather than by memcmp() + bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes + FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters + // https://dconf.org/2019/talks/alexandrescu.html + // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a + // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html + // Implementation: https://github.com/dlang/dmd/pull/9817 + bool noSharedAccess; // read/write access to shared memory objects + bool previewIn; // `in` means `[ref] scope const`, accepts rvalues + bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract + bool shortenedMethods; // allow => in normal function declarations + bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070 + bool fix16997; // fix integral promotions for unary + - ~ operators + // https://issues.dlang.org/show_bug.cgi?id=16997 + FeatureState dtorFields; // destruct fields of partially constructed objects + // https://issues.dlang.org/show_bug.cgi?id=14246 CHECKENABLE useInvariants; // generate class invariant checks CHECKENABLE useIn; // generate precondition checks CHECKENABLE useOut; // generate postcondition checks diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 680d9c8..48995db 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -1890,7 +1890,17 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg buf.printf("%uu", cast(uint)v); break; case Tint64: - buf.printf("%lldL", v); + if (v == long.min) + { + // https://issues.dlang.org/show_bug.cgi?id=23173 + // This is a special case because - is not part of the + // integer literal and 9223372036854775808L overflows a long + buf.writestring("cast(long)-9223372036854775808"); + } + else + { + buf.printf("%lldL", v); + } break; case Tuns64: buf.printf("%lluLU", v); @@ -2651,7 +2661,9 @@ void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool all assert(strlen(buffer.ptr) < BUFFER_LEN); if (allowHex) { - real_t r = CTFloat.parse(buffer.ptr); + bool isOutOfRange; + real_t r = CTFloat.parse(buffer.ptr, isOutOfRange); + //assert(!isOutOfRange); // test/compilable/test22725.c asserts here if (r != value) // if exact duplication CTFloat.sprint(buffer.ptr, 'a', value); } diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 5142daa..6695faa 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -160,6 +160,7 @@ immutable Msgtable[] msgtable = { "xopEquals", "__xopEquals" }, { "xopCmp", "__xopCmp" }, { "xtoHash", "__xtoHash" }, + { "__tmpfordtor" }, { "LINE", "__LINE__" }, { "FILE", "__FILE__" }, @@ -318,6 +319,8 @@ immutable Msgtable[] msgtable = { "_aaApply2" }, { "_d_arrayctor" }, { "_d_arraysetctor" }, + { "_d_arrayassign_l" }, + { "_d_arrayassign_r" }, // For pragma's { "Pinline", "inline" }, diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d index b42b4a1..7f92298 100644 --- a/gcc/d/dmd/identifier.d +++ b/gcc/d/dmd/identifier.d @@ -88,7 +88,7 @@ nothrow: return name.ptr; } - extern (D) override const(char)[] toString() const pure + extern (D) override const(char)[] toString() const pure @safe { return name; } diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 11afcdd..21bbde8 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -2531,7 +2531,7 @@ class Lexer auto sbufptr = cast(const(char)*)stringbuffer[].ptr; TOK result; bool isOutOfRange = false; - t.floatvalue = (isWellformedString ? CTFloat.parse(sbufptr, &isOutOfRange) : CTFloat.zero); + t.floatvalue = (isWellformedString ? CTFloat.parse(sbufptr, isOutOfRange) : CTFloat.zero); switch (*p) { case 'F': diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 5808c28..6bfb729 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -58,7 +58,6 @@ public: static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them static Dsymbols deferred2; // deferred Dsymbol's needing semantic2() run on them static Dsymbols deferred3; // deferred Dsymbol's needing semantic3() run on them - static unsigned dprogress; // progress resolving the deferred list static void _init(); diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 860cfa9..f2da41b 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -4407,30 +4407,46 @@ extern (C++) final class TypeFunction : TypeNext purityLevel(); + static bool mayHavePointers(Type t) + { + if (auto ts = t.isTypeStruct()) + { + auto sym = ts.sym; + if (sym.members && !sym.determineFields() && sym.type != Type.terror) + // struct is forward referenced, so "may have" pointers + return true; + } + return t.hasPointers(); + } + // See if p can escape via any of the other parameters if (purity == PURE.weak) { // Check escaping through parameters foreach (i, fparam; parameterList) { - if (fparam == p) - continue; Type t = fparam.type; if (!t) continue; - t = t.baseElemOf(); + t = t.baseElemOf(); // punch thru static arrays if (t.isMutable() && t.hasPointers()) { - if (fparam.isReference()) - { - } - else if (t.ty == Tarray || t.ty == Tpointer) + if (fparam.isReference() && fparam != p) + return stc; + + if (t.ty == Tdelegate) + return stc; // could escape thru delegate + + if (t.ty == Tclass) + return stc; + + /* if t is a pointer to mutable pointer + */ + if (auto tn = t.nextOf()) { - Type tn = t.nextOf().toBasetype(); - if (!(tn.isMutable() && tn.hasPointers())) - continue; + if (tn.isMutable() && mayHavePointers(tn)) + return stc; // escape through pointers } - return stc; } } diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index a2c364e..ce2769d 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -1999,7 +1999,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } } check(TOK.rightParenthesis); - check(TOK.semicolon); + check(TOK.semicolon, "static assert"); return new AST.StaticAssert(loc, exp, msg); } @@ -2648,7 +2648,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } } check(TOK.rightParenthesis); - check(TOK.semicolon); + check(TOK.semicolon, "invariant"); e = new AST.AssertExp(loc, e, msg); auto fbody = new AST.ExpStatement(loc, e); auto f = new AST.InvariantDeclaration(loc, token.loc, stc, null, fbody); @@ -4738,7 +4738,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); // advance past = auto t = parseType(); AST.Dsymbol s = new AST.AliasAssign(loc, ident, t, null); - check(TOK.semicolon); + check(TOK.semicolon, "alias reassignment"); addComment(s, comment); auto a = new AST.Dsymbols(); a.push(s); @@ -4774,7 +4774,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer auto s = new AST.AliasThis(loc, token.ident); nextToken(); check(TOK.this_); - check(TOK.semicolon); + check(TOK.semicolon, "`alias Identifier this`"); auto a = new AST.Dsymbols(); a.push(s); addComment(s, comment); @@ -4791,7 +4791,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer check(TOK.assign); auto s = new AliasThis(loc, token.ident); nextToken(); - check(TOK.semicolon); + check(TOK.semicolon, "`alias this = Identifier`"); auto a = new Dsymbols(); a.push(s); addComment(s, comment); @@ -5331,6 +5331,33 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error(loc, "instead of C-style syntax, use D-style `%s%s%s`", t.toChars(), sp, s); } + /***************************** + * Ad-hoc error message for missing or extra parens that close a condition. + * Params: + * start = "if", "while", etc. Must be 0 terminated. + * param = if the condition is a declaration, this will be non-null + * condition = if param is null, then this is the conditional Expression. If condition is null, + * then an error in the condition was already reported. + */ + private void closeCondition(string start, AST.Parameter param, AST.Expression condition) + { + string format; + if (token.value != TOK.rightParenthesis && condition) + { + format = "missing closing `)` after `%s (%s`"; + } + else + check(TOK.rightParenthesis); + if (token.value == TOK.rightParenthesis) + { + if (condition) // if not an error in condition + format = "extra `)` after `%s (%s)`"; + nextToken(); + } + if (format) + error(format.ptr, start.ptr, param ? "declaration".ptr : condition.toChars()); + } + /***************************************** * Parses `foreach` statements, `static foreach` statements and * `static foreach` declarations. @@ -5905,7 +5932,7 @@ LagainStc: { // mixin(string) AST.Expression e = parseAssignExp(); - check(TOK.semicolon); + check(TOK.semicolon, "mixin"); if (e.op == EXP.mixin_) { AST.MixinExp cpe = cast(AST.MixinExp)e; @@ -5961,12 +5988,12 @@ LagainStc: } case TOK.while_: { - AST.Parameter param = null; nextToken(); check(TOK.leftParenthesis); - param = parseAssignCondition(); - AST.Expression condition = parseExpression(); - check(TOK.rightParenthesis); + auto param = parseAssignCondition(); + auto condition = parseExpression(); + closeCondition("while", param, condition); + Loc endloc; AST.Statement _body = parseStatement(ParseStatementFlags.scope_, null, &endloc); s = new AST.WhileStatement(loc, condition, _body, endloc, param); @@ -5987,7 +6014,6 @@ LagainStc: case TOK.do_: { AST.Statement _body; - AST.Expression condition; nextToken(); const lookingForElseSave = lookingForElse; @@ -5996,8 +6022,8 @@ LagainStc: lookingForElse = lookingForElseSave; check(TOK.while_); check(TOK.leftParenthesis); - condition = parseExpression(); - check(TOK.rightParenthesis); + auto condition = parseExpression(); + closeCondition("do .. while", null, condition); if (token.value == TOK.semicolon) nextToken(); else @@ -6058,25 +6084,11 @@ LagainStc: } case TOK.if_: { - AST.Parameter param = null; - AST.Expression condition; - nextToken(); check(TOK.leftParenthesis); - param = parseAssignCondition(); - condition = parseExpression(); - if (token.value != TOK.rightParenthesis && condition) - { - error("missing closing `)` after `if (%s`", param ? "declaration".ptr : condition.toChars()); - } - else - check(TOK.rightParenthesis); - if (token.value == TOK.rightParenthesis) - { - if (condition) // if not an error in condition - error("extra `)` after `if (%s)`", param ? "declaration".ptr : condition.toChars()); - nextToken(); - } + auto param = parseAssignCondition(); + auto condition = parseExpression(); + closeCondition("if", param, condition); { const lookingForElseSave = lookingForElse; @@ -6223,7 +6235,7 @@ LagainStc: nextToken(); check(TOK.leftParenthesis); AST.Expression condition = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("switch", null, condition); AST.Statement _body = parseStatement(ParseStatementFlags.scope_); s = new AST.SwitchStatement(loc, condition, _body, isfinal); break; @@ -6402,7 +6414,7 @@ LagainStc: { nextToken(); exp = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("synchronized", null, exp); } else exp = null; @@ -6419,7 +6431,7 @@ LagainStc: nextToken(); check(TOK.leftParenthesis); exp = parseExpression(); - check(TOK.rightParenthesis); + closeCondition("with", null, exp); _body = parseStatement(ParseStatementFlags.scope_, null, &endloc); s = new AST.WithStatement(loc, exp, _body, endloc); break; @@ -6511,7 +6523,7 @@ LagainStc: if (peekNext() == TOK.leftParenthesis) { AST.Expression e = parseExpression(); - check(TOK.semicolon); + check(TOK.semicolon, "`import` Expression"); s = new AST.ExpStatement(loc, e); } else diff --git a/gcc/d/dmd/root/README.md b/gcc/d/dmd/root/README.md index 464f338..121d37c 100644 --- a/gcc/d/dmd/root/README.md +++ b/gcc/d/dmd/root/README.md @@ -2,25 +2,25 @@ | File | Purpose | |--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| -| [aav.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/aav.d) | An associative array implementation | -| [array.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/array.d) | A dynamic array implementation | -| [bitarray.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/bitarray.d) | A compact array of bits | -| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/complex.d) | A complex number type | -| [ctfloat.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/ctfloat.d) | A floating point type for compile-time calculations | -| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/env.d) | Modify environment variables | -| [file.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/file.d) | Read a file from disk and store it in memory | -| [filename.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d) | Encapsulate path and file names | -| [hash.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d) | Calculate a hash for a byte array | -| [longdouble.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/longdouble.d) | 80-bit floating point number implementation in case they are not natively supported | -| [man.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d) | Opens an online manual page | -| [optional.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d) | Implementation of an 'Optional' type | -| [port.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d) | Portable routines for functions that have different implementations on different platforms | -| [region.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d) | A region allocator | -| [response.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/response.d) | Parse command line arguments from response files | -| [rmem.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/rmem.d) | Allocate memory using `malloc` or the GC depending on the configuration | -| [rootobject.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/rootobject.d) | A root object that classes in dmd inherit from | -| [speller.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/speller.d) | Try to detect typos in identifiers | -| [string.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/string.d) | Various string related functions | -| [stringtable.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.d) | Specialized associative array with string keys stored in a variable length structure | -| [strtold.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/strtold.d) | D implementation of the standard C function `strtold` (String to long double) | -| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/utf.d) | Encoding/decoding Unicode text | +| [aav.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/aav.d) | An associative array implementation | +| [array.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/array.d) | A dynamic array implementation | +| [bitarray.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/bitarray.d) | A compact array of bits | +| [complex.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/complex.d) | A complex number type | +| [ctfloat.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/ctfloat.d) | A floating point type for compile-time calculations | +| [env.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/env.d) | Modify environment variables | +| [file.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/file.d) | Read a file from disk and store it in memory | +| [filename.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/filename.d) | Encapsulate path and file names | +| [hash.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/hash.d) | Calculate a hash for a byte array | +| [longdouble.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/longdouble.d) | 80-bit floating point number implementation in case they are not natively supported | +| [man.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/man.d) | Opens an online manual page | +| [optional.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/optional.d) | Implementation of an 'Optional' type | +| [port.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/port.d) | Portable routines for functions that have different implementations on different platforms | +| [region.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/region.d) | A region allocator | +| [response.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/response.d) | Parse command line arguments from response files | +| [rmem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/rmem.d) | Allocate memory using `malloc` or the GC depending on the configuration | +| [rootobject.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/rootobject.d) | A root object that classes in dmd inherit from | +| [speller.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/speller.d) | Try to detect typos in identifiers | +| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/string.d) | Various string related functions | +| [stringtable.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/stringtable.d) | Specialized associative array with string keys stored in a variable length structure | +| [strtold.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/strtold.d) | D implementation of the standard C function `strtold` (String to long double) | +| [utf.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/utf.d) | Encoding/decoding Unicode text | diff --git a/gcc/d/dmd/root/array.d b/gcc/d/dmd/root/array.d index c2eb3e1..212fe96 100644 --- a/gcc/d/dmd/root/array.d +++ b/gcc/d/dmd/root/array.d @@ -222,6 +222,16 @@ public: } } + extern (D) void insert(size_t index, T[] a) pure nothrow + { + size_t d = a.length; + reserve(d); + if (length != index) + memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof); + memcpy(data.ptr + index, a.ptr, d * T.sizeof); + length += d; + } + void insert(size_t index, T ptr) pure nothrow { reserve(1); @@ -414,6 +424,14 @@ unittest arrayA.zero(); foreach(e; arrayA) assert(e == 0); + + arrayA.setDim(0); + arrayA.pushSlice([5, 6]); + arrayA.insert(1, [1, 2]); + assert(arrayA[] == [5, 1, 2, 6]); + arrayA.insert(0, [7, 8]); + arrayA.insert(arrayA.length, [0, 9]); + assert(arrayA[] == [7, 8, 5, 1, 2, 6, 0, 9]); } /** diff --git a/gcc/d/dmd/root/ctfloat.d b/gcc/d/dmd/root/ctfloat.d index 5ccc7bf..8c2fe46 100644 --- a/gcc/d/dmd/root/ctfloat.d +++ b/gcc/d/dmd/root/ctfloat.d @@ -47,7 +47,7 @@ extern (C++) struct CTFloat static bool isInfinity(real_t r) pure; @system - static real_t parse(const(char)* literal, bool* isOutOfRange = null); + static real_t parse(const(char)* literal, out bool isOutOfRange); @system static int sprint(char* str, char fmt, real_t x); diff --git a/gcc/d/dmd/root/ctfloat.h b/gcc/d/dmd/root/ctfloat.h index 6b83dbf..5a6cf25 100644 --- a/gcc/d/dmd/root/ctfloat.h +++ b/gcc/d/dmd/root/ctfloat.h @@ -50,7 +50,7 @@ struct CTFloat static bool isSNaN(real_t r); static bool isInfinity(real_t r); - static real_t parse(const char *literal, bool *isOutOfRange = NULL); + static real_t parse(const char *literal, bool& isOutOfRange); static int sprint(char *str, char fmt, real_t x); static size_t hash(real_t a); diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 6f37770..ad4487f 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -472,9 +472,6 @@ private extern(C++) final class Semantic3Visitor : Visitor stc |= STC.variadic; } - if ((funcdecl.flags & FUNCFLAG.inferScope) && !(fparam.storageClass & STC.scope_)) - stc |= STC.maybescope; - stc |= fparam.storageClass & (STC.IOR | STC.return_ | STC.scope_ | STC.lazy_ | STC.final_ | STC.TYPECTOR | STC.nodtor | STC.returnScope | STC.register); v.storage_class = stc; v.dsymbolSemantic(sc2); diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index be95432..367c56b 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -1268,6 +1268,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) auto o = (*e.args)[0]; auto po = isParameter(o); auto s = getDsymbolWithoutExpCtx(o); + auto typeOfArg = isType(o); UserAttributeDeclaration udad = null; if (po) { @@ -1282,6 +1283,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc) //printf("getAttributes %s, attrs = %p, scope = %p\n", s.toChars(), s.userAttribDecl, s._scope); udad = s.userAttribDecl; } + else if (typeOfArg) + { + // If there is a type but no symbol, do nothing rather than erroring. + } else { version (none) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index b1f1b1f..b21ff79 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -1447,6 +1447,11 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) eparam.storageClass &= ~STC.auto_; eparam.storageClass |= STC.autoref; } + else if (eparam.storageClass & STC.ref_) + { + .error(loc, "cannot explicitly instantiate template function with `auto ref` parameter"); + errors = true; + } else { .error(loc, "`auto` can only be used as part of `auto ref` for template function parameters"); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 140df7e..b0ce870 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -986,11 +986,9 @@ public: else if ((postblit || destructor) && e->op != EXP::blit && e->op != EXP::construct) { - /* Generate: _d_arrayassign(ti, from, to); */ - this->result_ = build_libcall (LIBCALL_ARRAYASSIGN, e->type, 3, - build_typeinfo (e, etype), - d_array_convert (e->e2), - d_array_convert (e->e1)); + /* Assigning to a non-trivially copyable array has already been + handled by the front-end. */ + gcc_unreachable (); } else { @@ -1124,27 +1122,7 @@ public: /* All other kinds of lvalue or rvalue static array assignment. Array construction has already been handled by the front-end. */ gcc_assert (e->op != EXP::construct); - - /* Generate: _d_arrayassign_l() - or: _d_arrayassign_r() */ - libcall_fn libcall = (lvalue) - ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R; - tree elembuf = build_local_temp (build_ctype (etype)); - Type *arrtype = (e->type->ty == TY::Tsarray) - ? etype->arrayOf () : e->type; - tree result = build_libcall (libcall, arrtype, 4, - build_typeinfo (e, etype), - d_array_convert (e->e2), - d_array_convert (e->e1), - build_address (elembuf)); - - /* Cast the libcall result back to a static array. */ - if (e->type->ty == TY::Tsarray) - result = indirect_ref (build_ctype (e->type), - d_array_ptr (result)); - - this->result_ = result; - return; + gcc_unreachable (); } /* Simple assignment. */ diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index 459a283..282f22c 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -115,14 +115,7 @@ DEF_D_RUNTIME (ALLOCMEMORY, "_d_allocmemory", RT(VOIDPTR), P1(SIZE_T), DEF_D_RUNTIME (ARRAYCOPY, "_d_arraycopy", RT(ARRAY_VOID), P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), 0) -/* Used for array assignments from an existing array. The `set' variant is for - when the assignment value is a single element. */ -DEF_D_RUNTIME (ARRAYASSIGN, "_d_arrayassign", RT(ARRAY_VOID), - P3(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID), 0) -DEF_D_RUNTIME (ARRAYASSIGN_L, "_d_arrayassign_l", RT(ARRAY_VOID), - P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0) -DEF_D_RUNTIME (ARRAYASSIGN_R, "_d_arrayassign_r", RT(ARRAY_VOID), - P4(CONST_TYPEINFO, ARRAY_VOID, ARRAY_VOID, VOIDPTR), 0) +/* Used for array assignments from a single element. */ DEF_D_RUNTIME (ARRAYSETASSIGN, "_d_arraysetassign", RT(VOIDPTR), P4(VOIDPTR, VOIDPTR, SIZE_T, CONST_TYPEINFO), 0) diff --git a/gcc/dbxout.cc b/gcc/dbxout.cc deleted file mode 100644 index 878d528..0000000 --- a/gcc/dbxout.cc +++ /dev/null @@ -1,3936 +0,0 @@ -/* Output dbx-format symbol table information from GNU compiler. - Copyright (C) 1987-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - - -/* Output dbx-format symbol table data. - This consists of many symbol table entries, each of them - a .stabs assembler pseudo-op with four operands: - a "name" which is really a description of one symbol and its type, - a "code", which is a symbol defined in stab.h whose name starts with N_, - an unused operand always 0, - and a "value" which is an address or an offset. - The name is enclosed in doublequote characters. - - Each function, variable, typedef, and structure tag - has a symbol table entry to define it. - The beginning and end of each level of name scoping within - a function are also marked by special symbol table entries. - - The "name" consists of the symbol name, a colon, a kind-of-symbol letter, - and a data type number. The data type number may be followed by - "=" and a type definition; normally this will happen the first time - the type number is mentioned. The type definition may refer to - other types by number, and those type numbers may be followed - by "=" and nested definitions. - - This can make the "name" quite long. - When a name is more than 80 characters, we split the .stabs pseudo-op - into two .stabs pseudo-ops, both sharing the same "code" and "value". - The first one is marked as continued with a double-backslash at the - end of its "name". - - The kind-of-symbol letter distinguished function names from global - variables from file-scope variables from parameters from auto - variables in memory from typedef names from register variables. - See `dbxout_symbol'. - - The "code" is mostly redundant with the kind-of-symbol letter - that goes in the "name", but not entirely: for symbols located - in static storage, the "code" says which segment the address is in, - which controls how it is relocated. - - The "value" for a symbol in static storage - is the core address of the symbol (actually, the assembler - label for the symbol). For a symbol located in a stack slot - it is the stack offset; for one in a register, the register number. - For a typedef symbol, it is zero. - - If DEBUG_SYMS_TEXT is defined, all debugging symbols must be - output while in the text section. - - For more on data type definitions, see `dbxout_type'. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "function.h" -#include "rtl.h" -#include "tree.h" -#include "memmodel.h" -#include "tm_p.h" -#include "stringpool.h" -#include "insn-config.h" -#include "emit-rtl.h" -#include "cgraph.h" -#include "diagnostic-core.h" -#include "fold-const.h" -#include "varasm.h" -#include "stor-layout.h" -#include "reload.h" -#include "output.h" -#include "dbxout.h" -#include "toplev.h" -#include "debug.h" -#include "common/common-target.h" -#include "langhooks.h" -#include "expr.h" -#include "file-prefix-map.h" /* remap_debug_filename() */ -#include "flags.h" - -#ifdef XCOFF_DEBUGGING_INFO -#include "xcoffout.h" -#endif - -#ifndef ASM_STABS_OP -# ifdef XCOFF_DEBUGGING_INFO -# define ASM_STABS_OP "\t.stabx\t" -# else -# define ASM_STABS_OP "\t.stabs\t" -# endif -#endif - -#ifndef ASM_STABN_OP -#define ASM_STABN_OP "\t.stabn\t" -#endif - -#ifndef ASM_STABD_OP -#define ASM_STABD_OP "\t.stabd\t" -#endif - -#ifndef DBX_TYPE_DECL_STABS_CODE -#define DBX_TYPE_DECL_STABS_CODE N_LSYM -#endif - -#ifndef DBX_STATIC_CONST_VAR_CODE -#define DBX_STATIC_CONST_VAR_CODE N_FUN -#endif - -#ifndef DBX_REGPARM_STABS_CODE -#define DBX_REGPARM_STABS_CODE N_RSYM -#endif - -#ifndef DBX_REGPARM_STABS_LETTER -#define DBX_REGPARM_STABS_LETTER 'P' -#endif - -#ifndef NO_DBX_FUNCTION_END -#define NO_DBX_FUNCTION_END 0 -#endif - -#ifndef NO_DBX_BNSYM_ENSYM -#define NO_DBX_BNSYM_ENSYM 0 -#endif - -#ifndef NO_DBX_MAIN_SOURCE_DIRECTORY -#define NO_DBX_MAIN_SOURCE_DIRECTORY 0 -#endif - -#ifndef DBX_BLOCKS_FUNCTION_RELATIVE -#define DBX_BLOCKS_FUNCTION_RELATIVE 0 -#endif - -#ifndef DBX_LINES_FUNCTION_RELATIVE -#define DBX_LINES_FUNCTION_RELATIVE 0 -#endif - -#ifndef DBX_CONTIN_LENGTH -#define DBX_CONTIN_LENGTH 80 -#endif - -#ifndef DBX_CONTIN_CHAR -#define DBX_CONTIN_CHAR '\\' -#endif - -enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED}; - -/* Structure recording information about a C data type. - The status element says whether we have yet output - the definition of the type. TYPE_XREF says we have - output it as a cross-reference only. - The file_number and type_number elements are used if DBX_USE_BINCL - is defined. */ - -struct GTY(()) typeinfo { - enum typestatus status; - int file_number; - int type_number; -}; - -/* Vector recording information about C data types. - When we first notice a data type (a tree node), - we assign it a number using next_type_number. - That is its index in this vector. */ - -static GTY ((length ("typevec_len"))) struct typeinfo *typevec; - -/* Number of elements of space allocated in `typevec'. */ - -static GTY(()) int typevec_len; - -/* In dbx output, each type gets a unique number. - This is the number for the next type output. - The number, once assigned, is in the TYPE_SYMTAB_ADDRESS field. */ - -static GTY(()) int next_type_number; - -/* The C front end may call dbxout_symbol before dbxout_init runs. - We save all such decls in this list and output them when we get - to dbxout_init. */ - -static GTY(()) tree preinit_symbols; - -enum binclstatus {BINCL_NOT_REQUIRED, BINCL_PENDING, BINCL_PROCESSED}; - -/* When using N_BINCL in dbx output, each type number is actually a - pair of the file number and the type number within the file. - This is a stack of input files. */ - -struct dbx_file -{ - struct dbx_file *next; - int file_number; - int next_type_number; - enum binclstatus bincl_status; /* Keep track of lazy bincl. */ - const char *pending_bincl_name; /* Name of bincl. */ - struct dbx_file *prev; /* Chain to traverse all pending bincls. */ -}; - -/* This is the top of the stack. - - This is not saved for PCH, because restoring a PCH should not change it. - next_file_number does have to be saved, because the PCH may use some - file numbers; however, just before restoring a PCH, next_file_number - should always be 0 because we should not have needed any file numbers - yet. */ - -#if (defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)) \ - && defined (DBX_USE_BINCL) -static struct dbx_file *current_file; -#endif - -/* This is the next file number to use. */ - -static GTY(()) int next_file_number; - -/* A counter for dbxout_function_end. */ - -static GTY(()) int scope_labelno; - -/* A counter for dbxout_source_line. */ - -static GTY(()) int dbxout_source_line_counter; - -/* Number for the next N_SOL filename stabs label. The number 0 is reserved - for the N_SO filename stabs label. */ - -static GTY(()) int source_label_number = 1; - -/* Last source file name mentioned in a NOTE insn. */ - -static GTY(()) const char *lastfile; - -/* Last line number mentioned in a NOTE insn. */ - -static GTY(()) unsigned int lastlineno; - -/* Used by PCH machinery to detect if 'lastfile' should be reset to - base_input_file. */ -static GTY(()) int lastfile_is_base; - -/* Typical USG systems don't have stab.h, and they also have - no use for DBX-format debugging info. */ - -#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) - -#ifdef DBX_USE_BINCL -/* If zero then there is no pending BINCL. */ -static int pending_bincls = 0; -#endif - -/* The original input file name. */ -static const char *base_input_file; - -#ifdef DEBUG_SYMS_TEXT -#define FORCE_TEXT switch_to_section (current_function_section ()) -#else -#define FORCE_TEXT -#endif - -#include "gstab.h" - -/* 1 if PARM is passed to this function in memory. */ - -#define PARM_PASSED_IN_MEMORY(PARM) \ - (MEM_P (DECL_INCOMING_RTL (PARM))) - -/* A C expression for the integer offset value of an automatic variable - (N_LSYM) having address X (an RTX). */ -#ifndef DEBUGGER_AUTO_OFFSET -#define DEBUGGER_AUTO_OFFSET(X) \ - (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) -#endif - -/* A C expression for the integer offset value of an argument (N_PSYM) - having address X (an RTX). The nominal offset is OFFSET. - Note that we use OFFSET + 0 here to avoid the self-assign warning - when the macro is called in a context like - number = DEBUGGER_ARG_OFFSET(number, X) */ -#ifndef DEBUGGER_ARG_OFFSET -#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET + 0) -#endif - -/* This obstack holds the stab string currently being constructed. We - build it up here, then write it out, so we can split long lines up - properly (see dbxout_finish_complex_stabs). */ -static struct obstack stabstr_ob; -static size_t stabstr_last_contin_point; - -#ifdef DBX_USE_BINCL -static void emit_bincl_stab (const char *c); -static void emit_pending_bincls (void); -#endif -static inline void emit_pending_bincls_if_required (void); - -static void dbxout_init (const char *); - -static void dbxout_finish (const char *); -static void dbxout_start_source_file (unsigned, const char *); -static void dbxout_end_source_file (unsigned); -static void dbxout_typedefs (tree); -static void dbxout_type_index (tree); -static void dbxout_args (tree); -static void dbxout_type_fields (tree); -static void dbxout_type_method_1 (tree); -static void dbxout_type_methods (tree); -static void dbxout_range_type (tree, tree, tree); -static void dbxout_type (tree, int); -static bool print_int_cst_bounds_in_octal_p (tree, tree, tree); -static bool is_fortran (void); -static void dbxout_type_name (tree); -static void dbxout_class_name_qualifiers (tree); -static int dbxout_symbol_location (tree, tree, const char *, rtx); -static void dbxout_symbol_name (tree, const char *, int); -static void dbxout_common_name (tree, const char *, stab_code_type); -static const char *dbxout_common_check (tree, int *); -static void dbxout_early_global_decl (tree); -static void dbxout_late_global_decl (tree); -static void dbxout_type_decl (tree, int); -static void dbxout_handle_pch (unsigned); -static void debug_free_queue (void); - -/* The debug hooks structure. */ -#if defined (DBX_DEBUGGING_INFO) - -static void dbxout_source_line (unsigned int, unsigned int, const char *, - int, bool); -static void dbxout_switch_text_section (void); -static void dbxout_begin_prologue (unsigned int, unsigned int, const char *); -static void dbxout_source_file (const char *); -static void dbxout_function_end (tree); -static void dbxout_begin_function (tree); -static void dbxout_begin_block (unsigned, unsigned); -static void dbxout_end_block (unsigned, unsigned); -static void dbxout_function_decl (tree); - -const struct gcc_debug_hooks dbx_debug_hooks = -{ - dbxout_init, - dbxout_finish, - debug_nothing_charstar, - debug_nothing_void, - debug_nothing_int_charstar, - debug_nothing_int_charstar, - dbxout_start_source_file, - dbxout_end_source_file, - dbxout_begin_block, - dbxout_end_block, - debug_true_const_tree, /* ignore_block */ - dbxout_source_line, /* source_line */ - debug_nothing_int_int_charstar, /* set_ignored_loc */ - dbxout_begin_prologue, /* begin_prologue */ - debug_nothing_int_charstar, /* end_prologue */ - debug_nothing_int_charstar, /* begin_epilogue */ - debug_nothing_int_charstar, /* end_epilogue */ -#ifdef DBX_FUNCTION_FIRST - dbxout_begin_function, -#else - debug_nothing_tree, /* begin_function */ -#endif - debug_nothing_int, /* end_function */ - debug_nothing_tree, /* register_main_translation_unit */ - dbxout_function_decl, - dbxout_early_global_decl, /* early_global_decl */ - dbxout_late_global_decl, /* late_global_decl */ - dbxout_type_decl, /* type_decl */ - debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */ - debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */ - debug_nothing_tree_charstar_uhwi, /* register_external_die */ - debug_nothing_tree, /* deferred_inline_function */ - debug_nothing_tree, /* outlining_inline_function */ - debug_nothing_rtx_code_label, /* label */ - dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx_insn, /* var_location */ - debug_nothing_tree, /* inline_entry */ - debug_nothing_tree, /* size_function */ - dbxout_switch_text_section, /* switch_text_section */ - debug_nothing_tree_tree, /* set_name */ - 0, /* start_end_main_source_file */ - TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */ -}; -#endif /* DBX_DEBUGGING_INFO */ - -#if defined (XCOFF_DEBUGGING_INFO) -const struct gcc_debug_hooks xcoff_debug_hooks = -{ - dbxout_init, - dbxout_finish, - debug_nothing_charstar, - debug_nothing_void, - debug_nothing_int_charstar, - debug_nothing_int_charstar, - dbxout_start_source_file, - dbxout_end_source_file, - xcoffout_begin_block, - xcoffout_end_block, - debug_true_const_tree, /* ignore_block */ - xcoffout_source_line, - debug_nothing_int_int_charstar, /* set_ignored_loc */ - xcoffout_begin_prologue, /* begin_prologue */ - debug_nothing_int_charstar, /* end_prologue */ - debug_nothing_int_charstar, /* begin_epilogue */ - xcoffout_end_epilogue, - debug_nothing_tree, /* begin_function */ - xcoffout_end_function, - debug_nothing_tree, /* register_main_translation_unit */ - debug_nothing_tree, /* function_decl */ - dbxout_early_global_decl, /* early_global_decl */ - dbxout_late_global_decl, /* late_global_decl */ - dbxout_type_decl, /* type_decl */ - debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */ - debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */ - debug_nothing_tree_charstar_uhwi, /* register_external_die */ - debug_nothing_tree, /* deferred_inline_function */ - debug_nothing_tree, /* outlining_inline_function */ - debug_nothing_rtx_code_label, /* label */ - dbxout_handle_pch, /* handle_pch */ - debug_nothing_rtx_insn, /* var_location */ - debug_nothing_tree, /* inline_entry */ - debug_nothing_tree, /* size_function */ - debug_nothing_void, /* switch_text_section */ - debug_nothing_tree_tree, /* set_name */ - 0, /* start_end_main_source_file */ - TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */ -}; -#endif /* XCOFF_DEBUGGING_INFO */ - -/* Numeric formatting helper macro. Note that this does not handle - hexadecimal. */ -#define NUMBER_FMT_LOOP(P, NUM, BASE) \ - do \ - { \ - int digit = NUM % BASE; \ - NUM /= BASE; \ - *--P = digit + '0'; \ - } \ - while (NUM > 0) - -/* Utility: write a decimal integer NUM to asm_out_file. */ -void -dbxout_int (int num) -{ - char buf[64]; - char *p = buf + sizeof buf; - unsigned int unum; - - if (num == 0) - { - putc ('0', asm_out_file); - return; - } - if (num < 0) - { - putc ('-', asm_out_file); - unum = -(unsigned int) num; - } - else - unum = num; - - NUMBER_FMT_LOOP (p, unum, 10); - - while (p < buf + sizeof buf) - { - putc (*p, asm_out_file); - p++; - } -} - - -/* Primitives for emitting simple stabs directives. All other stabs - routines should use these functions instead of directly emitting - stabs. They are exported because machine-dependent code may need - to invoke them, e.g. in a DBX_OUTPUT_* macro whose definition - forwards to code in CPU.c. */ - -/* The following functions should all be called immediately after one - of the dbxout_begin_stab* functions (below). They write out - various things as the value of a stab. */ - -/* Write out a literal zero as the value of a stab. */ -void -dbxout_stab_value_zero (void) -{ - fputs ("0\n", asm_out_file); -} - -/* Write out the label LABEL as the value of a stab. */ -void -dbxout_stab_value_label (const char *label) -{ - assemble_name (asm_out_file, label); - putc ('\n', asm_out_file); -} - -/* Write out the difference of two labels, LABEL - BASE, as the value - of a stab. */ -void -dbxout_stab_value_label_diff (const char *label, const char *base) -{ - assemble_name (asm_out_file, label); - putc ('-', asm_out_file); - assemble_name (asm_out_file, base); - putc ('\n', asm_out_file); -} - -/* Write out an internal label as the value of a stab, and immediately - emit that internal label. This should be used only when - dbxout_stabd will not work. STEM is the name stem of the label, - COUNTERP is a pointer to a counter variable which will be used to - guarantee label uniqueness. */ -void -dbxout_stab_value_internal_label (const char *stem, int *counterp) -{ - char label[100]; - int counter = counterp ? (*counterp)++ : 0; - - ASM_GENERATE_INTERNAL_LABEL (label, stem, counter); - dbxout_stab_value_label (label); - targetm.asm_out.internal_label (asm_out_file, stem, counter); -} - -/* Write out the difference between BASE and an internal label as the - value of a stab, and immediately emit that internal label. STEM and - COUNTERP are as for dbxout_stab_value_internal_label. */ -void -dbxout_stab_value_internal_label_diff (const char *stem, int *counterp, - const char *base) -{ - char label[100]; - int counter = counterp ? (*counterp)++ : 0; - - ASM_GENERATE_INTERNAL_LABEL (label, stem, counter); - dbxout_stab_value_label_diff (label, base); - targetm.asm_out.internal_label (asm_out_file, stem, counter); -} - -/* The following functions produce specific kinds of stab directives. */ - -/* Write a .stabd directive with type STYPE and desc SDESC to asm_out_file. */ -void -dbxout_stabd (int stype, int sdesc) -{ - fputs (ASM_STABD_OP, asm_out_file); - dbxout_int (stype); - fputs (",0,", asm_out_file); - dbxout_int (sdesc); - putc ('\n', asm_out_file); -} - -/* Write a .stabn directive with type STYPE. This function stops - short of emitting the value field, which is the responsibility of - the caller (normally it will be either a symbol or the difference - of two symbols). */ - -void -dbxout_begin_stabn (int stype) -{ - fputs (ASM_STABN_OP, asm_out_file); - dbxout_int (stype); - fputs (",0,0,", asm_out_file); -} - -/* Write a .stabn directive with type N_SLINE and desc LINE. As above, - the value field is the responsibility of the caller. */ -void -dbxout_begin_stabn_sline (int lineno) -{ - fputs (ASM_STABN_OP, asm_out_file); - dbxout_int (N_SLINE); - fputs (",0,", asm_out_file); - dbxout_int (lineno); - putc (',', asm_out_file); -} - -/* Begin a .stabs directive with string "", type STYPE, and desc and - other fields 0. The value field is the responsibility of the - caller. This function cannot be used for .stabx directives. */ -void -dbxout_begin_empty_stabs (int stype) -{ - fputs (ASM_STABS_OP, asm_out_file); - fputs ("\"\",", asm_out_file); - dbxout_int (stype); - fputs (",0,0,", asm_out_file); -} - -/* Begin a .stabs directive with string STR, type STYPE, and desc 0. - The value field is the responsibility of the caller. */ -void -dbxout_begin_simple_stabs (const char *str, int stype) -{ - fputs (ASM_STABS_OP, asm_out_file); - output_quoted_string (asm_out_file, str); - putc (',', asm_out_file); - dbxout_int (stype); - fputs (",0,0,", asm_out_file); -} - -/* As above but use SDESC for the desc field. */ -void -dbxout_begin_simple_stabs_desc (const char *str, int stype, int sdesc) -{ - fputs (ASM_STABS_OP, asm_out_file); - output_quoted_string (asm_out_file, str); - putc (',', asm_out_file); - dbxout_int (stype); - fputs (",0,", asm_out_file); - dbxout_int (sdesc); - putc (',', asm_out_file); -} - -/* The next set of functions are entirely concerned with production of - "complex" .stabs directives: that is, .stabs directives whose - strings have to be constructed piecemeal. dbxout_type, - dbxout_symbol, etc. use these routines heavily. The string is queued - up in an obstack, then written out by dbxout_finish_complex_stabs, which - is also responsible for splitting it up if it exceeds DBX_CONTIN_LENGTH. - (You might think it would be more efficient to go straight to stdio - when DBX_CONTIN_LENGTH is 0 (i.e. no length limit) but that turns - out not to be the case, and anyway this needs fewer #ifdefs.) */ - -/* Begin a complex .stabs directive. If we can, write the initial - ASM_STABS_OP to the asm_out_file. */ - -static void -dbxout_begin_complex_stabs (void) -{ - emit_pending_bincls_if_required (); - FORCE_TEXT; - fputs (ASM_STABS_OP, asm_out_file); - putc ('"', asm_out_file); - gcc_assert (stabstr_last_contin_point == 0); -} - -/* As above, but do not force text or emit pending bincls. This is - used by dbxout_symbol_location, which needs to do something else. */ -static void -dbxout_begin_complex_stabs_noforcetext (void) -{ - fputs (ASM_STABS_OP, asm_out_file); - putc ('"', asm_out_file); - gcc_assert (stabstr_last_contin_point == 0); -} - -/* Add CHR, a single character, to the string being built. */ -#define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr) - -/* Add STR, a normal C string, to the string being built. */ -#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen (str)) - -/* Add the text of ID, an IDENTIFIER_NODE, to the string being built. */ -#define stabstr_I(id) obstack_grow (&stabstr_ob, \ - IDENTIFIER_POINTER (id), \ - IDENTIFIER_LENGTH (id)) - -/* Add NUM, a signed decimal number, to the string being built. */ -static void -stabstr_D (HOST_WIDE_INT num) -{ - char buf[64]; - char *p = buf + sizeof buf; - unsigned HOST_WIDE_INT unum; - - if (num == 0) - { - stabstr_C ('0'); - return; - } - if (num < 0) - { - stabstr_C ('-'); - unum = -(unsigned HOST_WIDE_INT) num; - } - else - unum = num; - - NUMBER_FMT_LOOP (p, unum, 10); - - obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p); -} - -/* Add NUM, an unsigned decimal number, to the string being built. */ -static void -stabstr_U (unsigned HOST_WIDE_INT num) -{ - char buf[64]; - char *p = buf + sizeof buf; - if (num == 0) - { - stabstr_C ('0'); - return; - } - NUMBER_FMT_LOOP (p, num, 10); - obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p); -} - -/* Add CST, an INTEGER_CST tree, to the string being built as an - unsigned octal number. This routine handles values which are - larger than a single HOST_WIDE_INT. */ -static void -stabstr_O (tree cst) -{ - int prec = TYPE_PRECISION (TREE_TYPE (cst)); - int res_pres = prec % 3; - int i; - unsigned int digit; - - /* Leading zero for base indicator. */ - stabstr_C ('0'); - - /* If the value is zero, the base indicator will serve as the value - all by itself. */ - if (wi::to_wide (cst) == 0) - return; - - /* GDB wants constants with no extra leading "1" bits, so - we need to remove any sign-extension that might be - present. */ - if (res_pres == 1) - { - digit = wi::extract_uhwi (wi::to_wide (cst), prec - 1, 1); - stabstr_C ('0' + digit); - } - else if (res_pres == 2) - { - digit = wi::extract_uhwi (wi::to_wide (cst), prec - 2, 2); - stabstr_C ('0' + digit); - } - - prec -= res_pres; - for (i = prec - 3; i >= 0; i = i - 3) - { - digit = wi::extract_uhwi (wi::to_wide (cst), i, 3); - stabstr_C ('0' + digit); - } -} - -/* Called whenever it is safe to break a stabs string into multiple - .stabs directives. If the current string has exceeded the limit - set by DBX_CONTIN_LENGTH, mark the current position in the buffer - as a continuation point by inserting DBX_CONTIN_CHAR (doubled if - it is a backslash) and a null character. */ -static inline void -stabstr_continue (void) -{ - if (DBX_CONTIN_LENGTH > 0 - && obstack_object_size (&stabstr_ob) - stabstr_last_contin_point - > DBX_CONTIN_LENGTH) - { - if (DBX_CONTIN_CHAR == '\\') - obstack_1grow (&stabstr_ob, '\\'); - obstack_1grow (&stabstr_ob, DBX_CONTIN_CHAR); - obstack_1grow (&stabstr_ob, '\0'); - stabstr_last_contin_point = obstack_object_size (&stabstr_ob); - } -} -#define CONTIN stabstr_continue () - -/* Macro subroutine of dbxout_finish_complex_stabs, which emits - all of the arguments to the .stabs directive after the string. - Overridden by xcoffout.h. CODE is the stabs code for this symbol; - LINE is the source line to write into the desc field (in extended - mode); SYM is the symbol itself. - - ADDR, LABEL, and NUMBER are three different ways to represent the - stabs value field. At most one of these should be nonzero. - - ADDR is used most of the time; it represents the value as an - RTL address constant. - - LABEL is used (currently) only for N_CATCH stabs; it represents - the value as a string suitable for assemble_name. - - NUMBER is used when the value is an offset from an implicit base - pointer (e.g. for a stack variable), or an index (e.g. for a - register variable). It represents the value as a decimal integer. */ - -#ifndef DBX_FINISH_STABS -#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER) \ -do { \ - int line_ = use_gnu_debug_info_extensions ? LINE : 0; \ - \ - dbxout_int (CODE); \ - fputs (",0,", asm_out_file); \ - dbxout_int (line_); \ - putc (',', asm_out_file); \ - if (ADDR) \ - output_addr_const (asm_out_file, ADDR); \ - else if (LABEL) \ - assemble_name (asm_out_file, LABEL); \ - else \ - dbxout_int (NUMBER); \ - putc ('\n', asm_out_file); \ -} while (0) -#endif - -/* Finish the emission of a complex .stabs directive. When DBX_CONTIN_LENGTH - is zero, this has only to emit the close quote and the remainder of - the arguments. When it is nonzero, the string has been marshalled in - stabstr_ob, and this routine is responsible for breaking it up into - DBX_CONTIN_LENGTH-sized chunks. - - SYM is the DECL of the symbol under consideration; it is used only - for its DECL_SOURCE_LINE. The other arguments are all passed directly - to DBX_FINISH_STABS; see above for details. */ - -static void -dbxout_finish_complex_stabs (tree sym, stab_code_type code, - rtx addr, const char *label, int number) -{ - int line ATTRIBUTE_UNUSED; - char *str; - size_t len; - - line = sym ? DECL_SOURCE_LINE (sym) : 0; - if (DBX_CONTIN_LENGTH > 0) - { - char *chunk; - size_t chunklen; - - /* Nul-terminate the growing string, then get its size and - address. */ - obstack_1grow (&stabstr_ob, '\0'); - - len = obstack_object_size (&stabstr_ob); - chunk = str = XOBFINISH (&stabstr_ob, char *); - - /* Within the buffer are a sequence of NUL-separated strings, - each of which is to be written out as a separate stab - directive. */ - for (;;) - { - chunklen = strlen (chunk); - fwrite (chunk, 1, chunklen, asm_out_file); - fputs ("\",", asm_out_file); - - /* Must add an extra byte to account for the NUL separator. */ - chunk += chunklen + 1; - len -= chunklen + 1; - - /* Only put a line number on the last stab in the sequence. */ - DBX_FINISH_STABS (sym, code, len == 0 ? line : 0, - addr, label, number); - if (len == 0) - break; - - fputs (ASM_STABS_OP, asm_out_file); - putc ('"', asm_out_file); - } - stabstr_last_contin_point = 0; - } - else - { - /* No continuations - we can put the whole string out at once. - It is faster to augment the string with the close quote and - comma than to do a two-character fputs. */ - obstack_grow (&stabstr_ob, "\",", 2); - len = obstack_object_size (&stabstr_ob); - str = XOBFINISH (&stabstr_ob, char *); - - fwrite (str, 1, len, asm_out_file); - DBX_FINISH_STABS (sym, code, line, addr, label, number); - } - obstack_free (&stabstr_ob, str); -} - -#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) - -/* When -gused is used, emit debug info for only used symbols. But in - addition to the standard intercepted debug_hooks there are some - direct calls into this file, i.e., dbxout_symbol, dbxout_parms, and - dbxout_reg_params. Those routines may also be called from a higher - level intercepted routine. So to prevent recording data for an inner - call to one of these for an intercept, we maintain an intercept - nesting counter (debug_nesting). We only save the intercepted - arguments if the nesting is 1. */ -static int debug_nesting = 0; - -static tree *symbol_queue; -static int symbol_queue_index = 0; -static int symbol_queue_size = 0; - -#define DBXOUT_DECR_NESTING \ - if (--debug_nesting == 0 && symbol_queue_index > 0) \ - { emit_pending_bincls_if_required (); debug_flush_symbol_queue (); } - -#define DBXOUT_DECR_NESTING_AND_RETURN(x) \ - do {--debug_nesting; return (x);} while (0) - -#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ - -#if defined (DBX_DEBUGGING_INFO) - -static void -dbxout_function_end (tree decl ATTRIBUTE_UNUSED) -{ - char lscope_label_name[100]; - - /* The Lscope label must be emitted even if we aren't doing anything - else; dbxout_block needs it. */ - switch_to_section (current_function_section ()); - - /* Convert Lscope into the appropriate format for local labels in case - the system doesn't insert underscores in front of user generated - labels. */ - ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno); - targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno); - - /* The N_FUN tag at the end of the function is a GNU extension, - which may be undesirable, and is unnecessary if we do not have - named sections. */ - if (!use_gnu_debug_info_extensions - || NO_DBX_FUNCTION_END - || !targetm_common.have_named_sections) - return; - - /* By convention, GCC will mark the end of a function with an N_FUN - symbol and an empty string. */ - if (crtl->has_bb_partition) - { - dbxout_begin_empty_stabs (N_FUN); - if (in_cold_section_p) - dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label, - crtl->subsections.cold_section_label); - else - dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label, - crtl->subsections.hot_section_label); - } - else - { - char begin_label[20]; - /* Reference current function start using LFBB. */ - ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); - dbxout_begin_empty_stabs (N_FUN); - dbxout_stab_value_label_diff (lscope_label_name, begin_label); - } - - if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols) - dbxout_stabd (N_ENSYM, 0); -} -#endif /* DBX_DEBUGGING_INFO */ - -/* Get lang description for N_SO stab. */ -static unsigned int ATTRIBUTE_UNUSED -get_lang_number (void) -{ - const char *language_string = lang_hooks.name; - if (lang_GNU_C ()) - return N_SO_C; - else if (lang_GNU_CXX ()) - return N_SO_CC; - else if (strcmp (language_string, "GNU F77") == 0) - return N_SO_FORTRAN; - else if (lang_GNU_Fortran ()) - return N_SO_FORTRAN90; /* CHECKME */ - else if (strcmp (language_string, "GNU Objective-C") == 0) - return N_SO_OBJC; - else if (strcmp (language_string, "GNU Objective-C++") == 0) - return N_SO_OBJCPLUS; - else - return 0; - -} - -static bool -is_fortran (void) -{ - unsigned int lang = get_lang_number (); - - return (lang == N_SO_FORTRAN) || (lang == N_SO_FORTRAN90); -} - -/* At the beginning of compilation, start writing the symbol table. - Initialize `typevec' and output the standard data types of C. */ - -static void -dbxout_init (const char *input_file_name) -{ - char ltext_label_name[100]; - bool used_ltext_label_name = false; - tree syms = lang_hooks.decls.getdecls (); - const char *mapped_name; - - typevec_len = 100; - typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len); - - /* stabstr_ob contains one string, which will be just fine with - 1-byte alignment. */ - obstack_specify_allocation (&stabstr_ob, 0, 1, xmalloc, free); - - /* Convert Ltext into the appropriate format for local labels in case - the system doesn't insert underscores in front of user generated - labels. */ - ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0); - - /* Put the current working directory in an N_SO symbol. */ - if (use_gnu_debug_info_extensions && !NO_DBX_MAIN_SOURCE_DIRECTORY) - { - static const char *cwd; - - if (!cwd) - { - cwd = get_src_pwd (); - if (cwd[0] == '\0') - cwd = "/"; - else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1])) - cwd = concat (cwd, "/", NULL); - cwd = remap_debug_filename (cwd); - } -#ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY - DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd); -#else /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ - dbxout_begin_simple_stabs_desc (cwd, N_SO, get_lang_number ()); - dbxout_stab_value_label (ltext_label_name); - used_ltext_label_name = true; -#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */ - } - - mapped_name = remap_debug_filename (input_file_name); -#ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME - DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name); -#else - dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ()); - dbxout_stab_value_label (ltext_label_name); - used_ltext_label_name = true; -#endif - - if (used_ltext_label_name) - { - switch_to_section (text_section); - targetm.asm_out.internal_label (asm_out_file, "Ltext", 0); - } - - /* Emit an N_OPT stab to indicate that this file was compiled by GCC. - The string used is historical. */ -#ifndef NO_DBX_GCC_MARKER - dbxout_begin_simple_stabs ("gcc2_compiled.", N_OPT); - dbxout_stab_value_zero (); -#endif - - base_input_file = lastfile = input_file_name; - - next_type_number = 1; - -#ifdef DBX_USE_BINCL - current_file = XNEW (struct dbx_file); - current_file->next = NULL; - current_file->file_number = 0; - current_file->next_type_number = 1; - next_file_number = 1; - current_file->prev = NULL; - current_file->bincl_status = BINCL_NOT_REQUIRED; - current_file->pending_bincl_name = NULL; -#endif - - /* Get all permanent types that have typedef names, and output them - all, except for those already output. Some language front ends - put these declarations in the top-level scope; some do not; - the latter are responsible for calling debug_hooks->type_decl from - their record_builtin_type function. */ - dbxout_typedefs (syms); - - if (preinit_symbols) - { - tree t; - for (t = nreverse (preinit_symbols); t; t = TREE_CHAIN (t)) - dbxout_symbol (TREE_VALUE (t), 0); - preinit_symbols = 0; - } -} - -/* Output any typedef names for types described by TYPE_DECLs in SYMS. */ - -static void -dbxout_typedefs (tree syms) -{ - for (; syms != NULL_TREE; syms = DECL_CHAIN (syms)) - { - if (TREE_CODE (syms) == TYPE_DECL) - { - tree type = TREE_TYPE (syms); - if (TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && COMPLETE_OR_VOID_TYPE_P (type) - && ! TREE_ASM_WRITTEN (TYPE_NAME (type))) - dbxout_symbol (TYPE_NAME (type), 0); - } - } -} - -#ifdef DBX_USE_BINCL -/* Emit BINCL stab using given name. */ -static void -emit_bincl_stab (const char *name) -{ - dbxout_begin_simple_stabs (name, N_BINCL); - dbxout_stab_value_zero (); -} - -/* If there are pending bincls then it is time to emit all of them. */ - -static inline void -emit_pending_bincls_if_required (void) -{ - if (pending_bincls) - emit_pending_bincls (); -} - -/* Emit all pending bincls. */ - -static void -emit_pending_bincls (void) -{ - struct dbx_file *f = current_file; - - /* Find first pending bincl. */ - while (f->bincl_status == BINCL_PENDING) - f = f->next; - - /* Now emit all bincls. */ - f = f->prev; - - while (f) - { - if (f->bincl_status == BINCL_PENDING) - { - emit_bincl_stab (f->pending_bincl_name); - - /* Update file number and status. */ - f->file_number = next_file_number++; - f->bincl_status = BINCL_PROCESSED; - } - if (f == current_file) - break; - f = f->prev; - } - - /* All pending bincls have been emitted. */ - pending_bincls = 0; -} - -#else - -static inline void -emit_pending_bincls_if_required (void) {} -#endif - -/* Change to reading from a new source file. Generate a N_BINCL stab. */ - -static void -dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED, - const char *filename ATTRIBUTE_UNUSED) -{ -#ifdef DBX_USE_BINCL - struct dbx_file *n = XNEW (struct dbx_file); - - n->next = current_file; - n->next_type_number = 1; - /* Do not assign file number now. - Delay it until we actually emit BINCL. */ - n->file_number = 0; - n->prev = NULL; - current_file->prev = n; - n->bincl_status = BINCL_PENDING; - n->pending_bincl_name = remap_debug_filename (filename); - pending_bincls = 1; - current_file = n; -#endif -} - -/* Revert to reading a previous source file. Generate a N_EINCL stab. */ - -static void -dbxout_end_source_file (unsigned int line ATTRIBUTE_UNUSED) -{ -#ifdef DBX_USE_BINCL - /* Emit EINCL stab only if BINCL is not pending. */ - if (current_file->bincl_status == BINCL_PROCESSED) - { - dbxout_begin_stabn (N_EINCL); - dbxout_stab_value_zero (); - } - current_file->bincl_status = BINCL_NOT_REQUIRED; - current_file = current_file->next; -#endif -} - -/* Handle a few odd cases that occur when trying to make PCH files work. */ - -static void -dbxout_handle_pch (unsigned at_end) -{ - if (! at_end) - { - /* When using the PCH, this file will be included, so we need to output - a BINCL. */ - dbxout_start_source_file (0, lastfile); - - /* The base file when using the PCH won't be the same as - the base file when it's being generated. */ - lastfile = NULL; - } - else - { - /* ... and an EINCL. */ - dbxout_end_source_file (0); - - /* Deal with cases where 'lastfile' was never actually changed. */ - lastfile_is_base = lastfile == NULL; - } -} - -#if defined (DBX_DEBUGGING_INFO) - -static bool dbxout_block (tree, int, tree, int); - -/* Output debugging info to FILE to switch to sourcefile FILENAME. */ - -static void -dbxout_source_file (const char *filename) -{ - if (lastfile == 0 && lastfile_is_base) - { - lastfile = base_input_file; - lastfile_is_base = 0; - } - - if (filename && (lastfile == 0 || strcmp (filename, lastfile))) - { - /* Don't change section amid function. */ - if (current_function_decl == NULL_TREE) - switch_to_section (text_section); - - dbxout_begin_simple_stabs (remap_debug_filename (filename), N_SOL); - dbxout_stab_value_internal_label ("Ltext", &source_label_number); - lastfile = filename; - } -} - -/* Output N_BNSYM, line number symbol entry, and local symbol at - function scope */ - -static void -dbxout_begin_prologue (unsigned int lineno, - unsigned int column ATTRIBUTE_UNUSED, - const char *filename) -{ - if (use_gnu_debug_info_extensions - && !NO_DBX_FUNCTION_END - && !NO_DBX_BNSYM_ENSYM - && !flag_debug_only_used_symbols) - dbxout_stabd (N_BNSYM, 0); - - /* pre-increment the scope counter */ - scope_labelno++; - - dbxout_source_line (lineno, 0, filename, 0, true); - /* Output function begin block at function scope, referenced - by dbxout_block, dbxout_source_line and dbxout_function_end. */ - emit_pending_bincls_if_required (); - targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno); -} - -/* Output a line number symbol entry for source file FILENAME and line - number LINENO. */ - -static void -dbxout_source_line (unsigned int lineno, unsigned int column ATTRIBUTE_UNUSED, - const char *filename, int discriminator ATTRIBUTE_UNUSED, - bool is_stmt ATTRIBUTE_UNUSED) -{ - dbxout_source_file (filename); - -#ifdef DBX_OUTPUT_SOURCE_LINE - DBX_OUTPUT_SOURCE_LINE (asm_out_file, lineno, dbxout_source_line_counter); -#else - if (DBX_LINES_FUNCTION_RELATIVE) - { - char begin_label[20]; - dbxout_begin_stabn_sline (lineno); - /* Reference current function start using LFBB. */ - ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); - dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter, - begin_label); - } - else - dbxout_stabd (N_SLINE, lineno); -#endif - lastlineno = lineno; -} - -/* Unfortunately, at least when emitting relative addresses, STABS - has no way to express multiple partitions. Represent a function - as two functions in this case. */ - -static void -dbxout_switch_text_section (void) -{ - /* The N_FUN tag at the end of the function is a GNU extension, - which may be undesirable, and is unnecessary if we do not have - named sections. */ - in_cold_section_p = !in_cold_section_p; - switch_to_section (current_function_section ()); - dbxout_block (DECL_INITIAL (current_function_decl), 0, - DECL_ARGUMENTS (current_function_decl), -1); - dbxout_function_end (current_function_decl); - in_cold_section_p = !in_cold_section_p; - - switch_to_section (current_function_section ()); - - tree context = decl_function_context (current_function_decl); - extern tree cold_function_name; - - dbxout_begin_complex_stabs (); - stabstr_I (cold_function_name); - stabstr_S (":f"); - - tree type = TREE_TYPE (current_function_decl); - if (TREE_TYPE (type)) - dbxout_type (TREE_TYPE (type), 0); - else - dbxout_type (void_type_node, 0); - - if (context != 0) - { - stabstr_C (','); - stabstr_I (cold_function_name); - stabstr_C (','); - stabstr_I (DECL_NAME (context)); - } - - dbxout_finish_complex_stabs (current_function_decl, N_FUN, 0, - crtl->subsections.cold_section_label, 0); - - /* pre-increment the scope counter */ - scope_labelno++; - - dbxout_source_line (lastlineno, 0, lastfile, 0, true); - /* Output function begin block at function scope, referenced - by dbxout_block, dbxout_source_line and dbxout_function_end. */ - emit_pending_bincls_if_required (); - targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno); -} - -/* Describe the beginning of an internal block within a function. */ - -static void -dbxout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n) -{ - emit_pending_bincls_if_required (); - targetm.asm_out.internal_label (asm_out_file, "LBB", n); -} - -/* Describe the end line-number of an internal block within a function. */ - -static void -dbxout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int n) -{ - emit_pending_bincls_if_required (); - targetm.asm_out.internal_label (asm_out_file, "LBE", n); -} - -/* Output dbx data for a function definition. - This includes a definition of the function name itself (a symbol), - definitions of the parameters (locating them in the parameter list) - and then output the block that makes up the function's body - (including all the auto variables of the function). */ - -static void -dbxout_function_decl (tree decl) -{ - emit_pending_bincls_if_required (); -#ifndef DBX_FUNCTION_FIRST - dbxout_begin_function (decl); -#endif - dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl), -1); - dbxout_function_end (decl); -} - -#endif /* DBX_DEBUGGING_INFO */ - -static void -dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED) -{ - /* NYI for non-dwarf. */ -} - -/* Debug information for a global DECL. Called from toplev.cc after - compilation proper has finished. */ -static void -dbxout_late_global_decl (tree decl) -{ - if (VAR_P (decl) && !DECL_EXTERNAL (decl)) - { - int saved_tree_used = TREE_USED (decl); - TREE_USED (decl) = 1; - dbxout_symbol (decl, 0); - TREE_USED (decl) = saved_tree_used; - } -} - -/* This is just a function-type adapter; dbxout_symbol does exactly - what we want but returns an int. */ -static void -dbxout_type_decl (tree decl, int local) -{ - dbxout_symbol (decl, local); -} - -/* At the end of compilation, finish writing the symbol table. - The default is to call debug_free_queue but do nothing else. */ - -static void -dbxout_finish (const char *filename ATTRIBUTE_UNUSED) -{ -#ifdef DBX_OUTPUT_MAIN_SOURCE_FILE_END - DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename); -#elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END - { - switch_to_section (text_section); - dbxout_begin_empty_stabs (N_SO); - dbxout_stab_value_internal_label ("Letext", 0); - } -#endif - debug_free_queue (); -} - -/* Output the index of a type. */ - -static void -dbxout_type_index (tree type) -{ -#ifndef DBX_USE_BINCL - stabstr_D (TYPE_SYMTAB_ADDRESS (type)); -#else - struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)]; - stabstr_C ('('); - stabstr_D (t->file_number); - stabstr_C (','); - stabstr_D (t->type_number); - stabstr_C (')'); -#endif -} - - -/* Generate the symbols for any queued up type symbols we encountered - while generating the type info for some originally used symbol. - This might generate additional entries in the queue. Only when - the nesting depth goes to 0 is this routine called. */ - -static void -debug_flush_symbol_queue (void) -{ - int i; - - /* Make sure that additionally queued items are not flushed - prematurely. */ - - ++debug_nesting; - - for (i = 0; i < symbol_queue_index; ++i) - { - /* If we pushed queued symbols then such symbols must be - output no matter what anyone else says. Specifically, - we need to make sure dbxout_symbol() thinks the symbol was - used and also we need to override TYPE_DECL_SUPPRESS_DEBUG - which may be set for outside reasons. */ - int saved_tree_used = TREE_USED (symbol_queue[i]); - int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]); - TREE_USED (symbol_queue[i]) = 1; - TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0; - -#ifdef DBX_DEBUGGING_INFO - dbxout_symbol (symbol_queue[i], 0); -#endif - - TREE_USED (symbol_queue[i]) = saved_tree_used; - TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug; - } - - symbol_queue_index = 0; - --debug_nesting; -} - -/* Queue a type symbol needed as part of the definition of a decl - symbol. These symbols are generated when debug_flush_symbol_queue() - is called. */ - -static void -debug_queue_symbol (tree decl) -{ - if (symbol_queue_index >= symbol_queue_size) - { - symbol_queue_size += 10; - symbol_queue = XRESIZEVEC (tree, symbol_queue, symbol_queue_size); - } - - symbol_queue[symbol_queue_index++] = decl; -} - -/* Free symbol queue. */ -static void -debug_free_queue (void) -{ - if (symbol_queue) - { - free (symbol_queue); - symbol_queue = NULL; - symbol_queue_size = 0; - } -} - -/* Used in several places: evaluates to '0' for a private decl, - '1' for a protected decl, '2' for a public decl. */ -#define DECL_ACCESSIBILITY_CHAR(DECL) \ -(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2') - -/* Subroutine of `dbxout_type'. Output the type fields of TYPE. - This must be a separate function because anonymous unions require - recursive calls. */ - -static void -dbxout_type_fields (tree type) -{ - tree tem; - - /* Output the name, type, position (in bits), size (in bits) of each - field that we can support. */ - for (tem = TYPE_FIELDS (type); tem; tem = DECL_CHAIN (tem)) - { - /* If one of the nodes is an error_mark or its type is then - return early. */ - if (error_operand_p (tem)) - return; - - /* Omit here local type decls until we know how to support them. */ - if (TREE_CODE (tem) == TYPE_DECL - || TREE_CODE (tem) == TEMPLATE_DECL - /* Member functions emitted after fields. */ - || TREE_CODE (tem) == FUNCTION_DECL - /* Omit here the nameless fields that are used to skip bits. */ - || DECL_IGNORED_P (tem) - /* Omit fields whose position or size are variable or too large to - represent. */ - || (TREE_CODE (tem) == FIELD_DECL - && (! tree_fits_shwi_p (bit_position (tem)) - || ! DECL_SIZE (tem) - || ! tree_fits_uhwi_p (DECL_SIZE (tem))))) - continue; - - else if (TREE_CODE (tem) != CONST_DECL) - { - /* Continue the line if necessary, - but not before the first field. */ - if (tem != TYPE_FIELDS (type)) - CONTIN; - - if (DECL_NAME (tem)) - stabstr_I (DECL_NAME (tem)); - stabstr_C (':'); - - if (use_gnu_debug_info_extensions - && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) - || TREE_CODE (tem) != FIELD_DECL)) - { - stabstr_C ('/'); - stabstr_C (DECL_ACCESSIBILITY_CHAR (tem)); - } - - dbxout_type ((TREE_CODE (tem) == FIELD_DECL - && DECL_BIT_FIELD_TYPE (tem)) - ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0); - - if (VAR_P (tem)) - { - if (TREE_STATIC (tem) && use_gnu_debug_info_extensions) - { - tree name = DECL_ASSEMBLER_NAME (tem); - - stabstr_C (':'); - stabstr_I (name); - stabstr_C (';'); - } - else - /* If TEM is non-static, GDB won't understand it. */ - stabstr_S (",0,0;"); - } - else - { - stabstr_C (','); - stabstr_D (int_bit_position (tem)); - stabstr_C (','); - stabstr_D (tree_to_uhwi (DECL_SIZE (tem))); - stabstr_C (';'); - } - } - } -} - -/* Subroutine of `dbxout_type_methods'. Output debug info about the - method described DECL. */ - -static void -dbxout_type_method_1 (tree decl) -{ - char c1 = 'A', c2; - - if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) - c2 = '?'; - else /* it's a METHOD_TYPE. */ - { - tree firstarg = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))); - /* A for normal functions. - B for `const' member functions. - C for `volatile' member functions. - D for `const volatile' member functions. */ - if (TYPE_READONLY (TREE_TYPE (firstarg))) - c1 += 1; - if (TYPE_VOLATILE (TREE_TYPE (firstarg))) - c1 += 2; - - if (DECL_VINDEX (decl)) - c2 = '*'; - else - c2 = '.'; - } - - /* ??? Output the mangled name, which contains an encoding of the - method's type signature. May not be necessary anymore. */ - stabstr_C (':'); - stabstr_I (DECL_ASSEMBLER_NAME (decl)); - stabstr_C (';'); - stabstr_C (DECL_ACCESSIBILITY_CHAR (decl)); - stabstr_C (c1); - stabstr_C (c2); - - if (DECL_VINDEX (decl) && tree_fits_shwi_p (DECL_VINDEX (decl))) - { - stabstr_D (tree_to_shwi (DECL_VINDEX (decl))); - stabstr_C (';'); - dbxout_type (DECL_CONTEXT (decl), 0); - stabstr_C (';'); - } -} - -/* Subroutine of `dbxout_type'. Output debug info about the member - functions defined in TYPE. */ - -static void -dbxout_type_methods (tree type) -{ - for (tree fndecl = TYPE_FIELDS (type); fndecl;) - { - int need_prefix = 1; - - /* Group together all the methods for the same operation. - These differ in the types of the arguments. */ - for (tree last = NULL_TREE; - fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last)); - fndecl = DECL_CHAIN (fndecl)) - /* Output the name of the field (after overloading), as - well as the name of the field before overloading, along - with its parameter list */ - { - /* Skip non-functions. */ - if (TREE_CODE (fndecl) != FUNCTION_DECL) - continue; - - /* Also ignore abstract methods; those are only interesting to - the DWARF backends. */ - if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT_P (fndecl)) - continue; - - CONTIN; - - last = fndecl; - - /* Redundantly output the plain name, since that's what gdb - expects. */ - if (need_prefix) - { - stabstr_I (DECL_NAME (fndecl)); - stabstr_S ("::"); - need_prefix = 0; - } - - dbxout_type (TREE_TYPE (fndecl), 0); - dbxout_type_method_1 (fndecl); - } - if (!need_prefix) - stabstr_C (';'); - } -} - -/* Emit a "range" type specification, which has the form: - "r<index type>;<lower bound>;<upper bound>;". - TYPE is an INTEGER_TYPE, LOW and HIGH are the bounds. */ - -static void -dbxout_range_type (tree type, tree low, tree high) -{ - stabstr_C ('r'); - if (TREE_TYPE (type)) - dbxout_type (TREE_TYPE (type), 0); - else if (TREE_CODE (type) != INTEGER_TYPE) - dbxout_type (type, 0); - else - { - /* Traditionally, we made sure 'int' was type 1, and builtin types - were defined to be sub-ranges of int. Unfortunately, this - does not allow us to distinguish true sub-ranges from integer - types. So, instead we define integer (non-sub-range) types as - sub-ranges of themselves. This matters for Chill. If this isn't - a subrange type, then we want to define it in terms of itself. - However, in C, this may be an anonymous integer type, and we don't - want to emit debug info referring to it. Just calling - dbxout_type_index won't work anyways, because the type hasn't been - defined yet. We make this work for both cases by checked to see - whether this is a defined type, referring to it if it is, and using - 'int' otherwise. */ - if (TYPE_SYMTAB_ADDRESS (type) != 0) - dbxout_type_index (type); - else - dbxout_type_index (integer_type_node); - } - - stabstr_C (';'); - if (low && tree_fits_shwi_p (low)) - { - if (print_int_cst_bounds_in_octal_p (type, low, high)) - stabstr_O (low); - else - stabstr_D (tree_to_shwi (low)); - } - else - stabstr_C ('0'); - - stabstr_C (';'); - if (high && tree_fits_shwi_p (high)) - { - if (print_int_cst_bounds_in_octal_p (type, low, high)) - stabstr_O (high); - else - stabstr_D (tree_to_shwi (high)); - stabstr_C (';'); - } - else - stabstr_S ("-1;"); -} - - -/* Output a reference to a type. If the type has not yet been - described in the dbx output, output its definition now. - For a type already defined, just refer to its definition - using the type number. - - If FULL is nonzero, and the type has been described only with - a forward-reference, output the definition now. - If FULL is zero in this case, just refer to the forward-reference - using the number previously allocated. */ - -static void -dbxout_type (tree type, int full) -{ - static int anonymous_type_number = 0; - tree tem, main_variant, low, high; - - if (TREE_CODE (type) == INTEGER_TYPE) - { - if (TREE_TYPE (type) == 0) - { - low = TYPE_MIN_VALUE (type); - high = TYPE_MAX_VALUE (type); - } - - else if (subrange_type_for_debug_p (type, &low, &high)) - ; - - /* If this is a subtype that should not be emitted as a subrange type, - use the base type. */ - else - { - type = TREE_TYPE (type); - low = TYPE_MIN_VALUE (type); - high = TYPE_MAX_VALUE (type); - } - } - - /* If there was an input error and we don't really have a type, - avoid crashing and write something that is at least valid - by assuming `int'. */ - if (type == error_mark_node) - type = integer_type_node; - else - { - if (TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type))) - full = 0; - } - - /* Try to find the "main variant" with the same name. */ - if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) - main_variant = TREE_TYPE (TYPE_NAME (type)); - else - main_variant = TYPE_MAIN_VARIANT (type); - - /* If we are not using extensions, stabs does not distinguish const and - volatile, so there is no need to make them separate types. */ - if (!use_gnu_debug_info_extensions) - type = main_variant; - - if (TYPE_SYMTAB_ADDRESS (type) == 0) - { - /* Type has no dbx number assigned. Assign next available number. */ - TYPE_SYMTAB_ADDRESS (type) = next_type_number++; - - /* Make sure type vector is long enough to record about this type. */ - - if (next_type_number == typevec_len) - { - typevec = GGC_RESIZEVEC (struct typeinfo, typevec, typevec_len * 2); - memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]); - typevec_len *= 2; - } - -#ifdef DBX_USE_BINCL - emit_pending_bincls_if_required (); - typevec[TYPE_SYMTAB_ADDRESS (type)].file_number - = current_file->file_number; - typevec[TYPE_SYMTAB_ADDRESS (type)].type_number - = current_file->next_type_number++; -#endif - } - - if (flag_debug_only_used_symbols) - { - if ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && TYPE_STUB_DECL (type) - && DECL_P (TYPE_STUB_DECL (type)) - && ! DECL_IGNORED_P (TYPE_STUB_DECL (type))) - debug_queue_symbol (TYPE_STUB_DECL (type)); - else if (TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) - debug_queue_symbol (TYPE_NAME (type)); - } - - /* Output the number of this type, to refer to it. */ - dbxout_type_index (type); - -#ifdef DBX_TYPE_DEFINED - if (DBX_TYPE_DEFINED (type)) - return; -#endif - - /* If this type's definition has been output or is now being output, - that is all. */ - - switch (typevec[TYPE_SYMTAB_ADDRESS (type)].status) - { - case TYPE_UNSEEN: - break; - case TYPE_XREF: - /* If we have already had a cross reference, - and either that's all we want or that's the best we could do, - don't repeat the cross reference. - Sun dbx crashes if we do. */ - if (! full || !COMPLETE_TYPE_P (type) - /* No way in DBX fmt to describe a variable size. */ - || ! tree_fits_uhwi_p (TYPE_SIZE (type))) - return; - break; - case TYPE_DEFINED: - return; - } - -#ifdef DBX_NO_XREFS - /* For systems where dbx output does not allow the `=xsNAME:' syntax, - leave the type-number completely undefined rather than output - a cross-reference. If we have already used GNU debug info extensions, - then it is OK to output a cross reference. This is necessary to get - proper C++ debug output. */ - if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && ! use_gnu_debug_info_extensions) - /* We must use the same test here as we use twice below when deciding - whether to emit a cross-reference. */ - if ((TYPE_NAME (type) != 0 - && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_IGNORED_P (TYPE_NAME (type))) - && !full) - || !COMPLETE_TYPE_P (type) - /* No way in DBX fmt to describe a variable size. */ - || ! tree_fits_uhwi_p (TYPE_SIZE (type))) - { - typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; - return; - } -#endif - - /* Output a definition now. */ - stabstr_C ('='); - - /* Mark it as defined, so that if it is self-referent - we will not get into an infinite recursion of definitions. */ - - typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED; - - /* If this type is a variant of some other, hand off. Types with - different names are usefully distinguished. We only distinguish - cv-qualified types if we're using extensions. */ - if (TYPE_READONLY (type) > TYPE_READONLY (main_variant)) - { - stabstr_C ('k'); - dbxout_type (build_type_variant (type, 0, TYPE_VOLATILE (type)), 0); - return; - } - else if (TYPE_VOLATILE (type) > TYPE_VOLATILE (main_variant)) - { - stabstr_C ('B'); - dbxout_type (build_type_variant (type, TYPE_READONLY (type), 0), 0); - return; - } - else if (main_variant != TYPE_MAIN_VARIANT (type)) - { - if (flag_debug_only_used_symbols) - { - tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); - - if ((TREE_CODE (orig_type) == RECORD_TYPE - || TREE_CODE (orig_type) == UNION_TYPE - || TREE_CODE (orig_type) == QUAL_UNION_TYPE - || TREE_CODE (orig_type) == ENUMERAL_TYPE) - && TYPE_STUB_DECL (orig_type) - && ! DECL_IGNORED_P (TYPE_STUB_DECL (orig_type))) - debug_queue_symbol (TYPE_STUB_DECL (orig_type)); - } - /* 'type' is a typedef; output the type it refers to. */ - dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0); - return; - } - /* else continue. */ - - switch (TREE_CODE (type)) - { - case VOID_TYPE: - case NULLPTR_TYPE: - case LANG_TYPE: - case OPAQUE_TYPE: - /* For a void type, just define it as itself; i.e., "5=5". - This makes us consider it defined - without saying what it is. The debugger will make it - a void type when the reference is seen, and nothing will - ever override that default. */ - dbxout_type_index (type); - break; - - case INTEGER_TYPE: - if (type == char_type_node && ! TYPE_UNSIGNED (type)) - { - /* Output the type `char' as a subrange of itself! - I don't understand this definition, just copied it - from the output of pcc. - This used to use `r2' explicitly and we used to - take care to make sure that `char' was type number 2. */ - stabstr_C ('r'); - dbxout_type_index (type); - stabstr_S (";0;127;"); - } - - /* If this is a subtype of another integer type, always prefer to - write it as a subtype. */ - else if (TREE_TYPE (type) != 0 - && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE) - { - /* If the size is non-standard, say what it is if we can use - GDB extensions. */ - - if (use_gnu_debug_info_extensions - && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) - { - stabstr_S ("@s"); - stabstr_D (TYPE_PRECISION (type)); - stabstr_C (';'); - } - - dbxout_range_type (type, low, high); - } - - else - { - /* If the size is non-standard, say what it is if we can use - GDB extensions. */ - - if (use_gnu_debug_info_extensions - && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) - { - stabstr_S ("@s"); - stabstr_D (TYPE_PRECISION (type)); - stabstr_C (';'); - } - - if (print_int_cst_bounds_in_octal_p (type, low, high)) - { - stabstr_C ('r'); - - /* If this type derives from another type, output type index of - parent type. This is particularly important when parent type - is an enumerated type, because not generating the parent type - index would transform the definition of this enumerated type - into a plain unsigned type. */ - if (TREE_TYPE (type) != 0) - dbxout_type_index (TREE_TYPE (type)); - else - dbxout_type_index (type); - - stabstr_C (';'); - stabstr_O (low); - stabstr_C (';'); - stabstr_O (high); - stabstr_C (';'); - } - - else - /* Output other integer types as subranges of `int'. */ - dbxout_range_type (type, low, high); - } - - break; - - case REAL_TYPE: - case FIXED_POINT_TYPE: - /* This used to say `r1' and we used to take care - to make sure that `int' was type number 1. */ - stabstr_C ('r'); - dbxout_type_index (integer_type_node); - stabstr_C (';'); - stabstr_D (int_size_in_bytes (type)); - stabstr_S (";0;"); - break; - - case BOOLEAN_TYPE: - if (use_gnu_debug_info_extensions) - { - stabstr_S ("@s"); - stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); - stabstr_S (";-16;"); - } - else /* Define as enumeral type (False, True) */ - stabstr_S ("eFalse:0,True:1,;"); - break; - - case COMPLEX_TYPE: - /* Differs from the REAL_TYPE by its new data type number. - R3 is NF_COMPLEX. We don't try to use any of the other NF_* - codes since gdb doesn't care anyway. */ - - if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) - { - stabstr_S ("R3;"); - stabstr_D (2 * int_size_in_bytes (TREE_TYPE (type))); - stabstr_S (";0;"); - } - else - { - /* Output a complex integer type as a structure, - pending some other way to do it. */ - stabstr_C ('s'); - stabstr_D (int_size_in_bytes (type)); - - stabstr_S ("real:"); - dbxout_type (TREE_TYPE (type), 0); - stabstr_S (",0,"); - stabstr_D (TYPE_PRECISION (TREE_TYPE (type))); - - stabstr_S (";imag:"); - dbxout_type (TREE_TYPE (type), 0); - stabstr_C (','); - stabstr_D (TYPE_PRECISION (TREE_TYPE (type))); - stabstr_C (','); - stabstr_D (TYPE_PRECISION (TREE_TYPE (type))); - stabstr_S (";;"); - } - break; - - case ARRAY_TYPE: - /* Make arrays of packed bits look like bitstrings for chill. */ - if (TYPE_PACKED (type) && use_gnu_debug_info_extensions) - { - stabstr_S ("@s"); - stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type)); - stabstr_S (";@S;S"); - dbxout_type (TYPE_DOMAIN (type), 0); - break; - } - - /* Output "a" followed by a range type definition - for the index type of the array - followed by a reference to the target-type. - ar1;0;N;M for a C array of type M and size N+1. */ - /* Check if a character string type, which in Chill is - different from an array of characters. */ - if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions) - { - stabstr_S ("@S;"); - } - tem = TYPE_DOMAIN (type); - if (tem == NULL) - { - stabstr_S ("ar"); - dbxout_type_index (integer_type_node); - stabstr_S (";0;-1;"); - } - else - { - stabstr_C ('a'); - dbxout_range_type (tem, TYPE_MIN_VALUE (tem), TYPE_MAX_VALUE (tem)); - } - - dbxout_type (TREE_TYPE (type), 0); - break; - - case VECTOR_TYPE: - /* Make vectors look like an array. */ - if (use_gnu_debug_info_extensions) - stabstr_S ("@V;"); - - /* Output "a" followed by a range type definition - for the index type of the array - followed by a reference to the target-type. - ar1;0;N;M for a C array of type M and size N+1. */ - stabstr_C ('a'); - dbxout_range_type (integer_type_node, size_zero_node, - size_int (TYPE_VECTOR_SUBPARTS (type) - 1)); - - dbxout_type (TREE_TYPE (type), 0); - break; - - case RECORD_TYPE: - case UNION_TYPE: - case QUAL_UNION_TYPE: - { - tree binfo = TYPE_BINFO (type); - - /* Output a structure type. We must use the same test here as we - use in the DBX_NO_XREFS case above. */ - if ((TYPE_NAME (type) != 0 - && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_IGNORED_P (TYPE_NAME (type))) - && !full) - || !COMPLETE_TYPE_P (type) - /* No way in DBX fmt to describe a variable size. */ - || ! tree_fits_uhwi_p (TYPE_SIZE (type))) - { - /* If the type is just a cross reference, output one - and mark the type as partially described. - If it later becomes defined, we will output - its real definition. - If the type has a name, don't nest its definition within - another type's definition; instead, output an xref - and let the definition come when the name is defined. */ - stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu"); - if (TYPE_IDENTIFIER (type)) - { - /* Note that the C frontend creates for anonymous variable - length records/unions TYPE_NAME with DECL_NAME NULL. */ - dbxout_type_name (type); - } - else - { - stabstr_S ("$$"); - stabstr_D (anonymous_type_number++); - } - - stabstr_C (':'); - typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; - break; - } - - /* Identify record or union, and print its size. */ - stabstr_C ((TREE_CODE (type) == RECORD_TYPE) ? 's' : 'u'); - stabstr_D (int_size_in_bytes (type)); - - if (binfo) - { - int i; - tree child; - vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo); - - if (use_gnu_debug_info_extensions) - { - if (BINFO_N_BASE_BINFOS (binfo)) - { - stabstr_C ('!'); - stabstr_U (BINFO_N_BASE_BINFOS (binfo)); - stabstr_C (','); - } - } - for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++) - { - tree access = (accesses ? (*accesses)[i] : access_public_node); - - if (use_gnu_debug_info_extensions) - { - stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0'); - stabstr_C (access == access_public_node ? '2' : - access == access_protected_node - ? '1' :'0'); - if (BINFO_VIRTUAL_P (child) - && (lang_GNU_CXX () - || strcmp (lang_hooks.name, "GNU Objective-C++") == 0)) - /* For a virtual base, print the (negative) - offset within the vtable where we must look - to find the necessary adjustment. */ - stabstr_D - (tree_to_shwi (BINFO_VPTR_FIELD (child)) - * BITS_PER_UNIT); - else - stabstr_D (tree_to_shwi (BINFO_OFFSET (child)) - * BITS_PER_UNIT); - stabstr_C (','); - dbxout_type (BINFO_TYPE (child), 0); - stabstr_C (';'); - } - else - { - /* Print out the base class information with - fields which have the same names at the types - they hold. */ - dbxout_type_name (BINFO_TYPE (child)); - stabstr_C (':'); - dbxout_type (BINFO_TYPE (child), full); - stabstr_C (','); - stabstr_D (tree_to_shwi (BINFO_OFFSET (child)) - * BITS_PER_UNIT); - stabstr_C (','); - stabstr_D - (tree_to_shwi (TYPE_SIZE (BINFO_TYPE (child))) - * BITS_PER_UNIT); - stabstr_C (';'); - } - } - } - } - - /* Write out the field declarations. */ - dbxout_type_fields (type); - if (use_gnu_debug_info_extensions) - dbxout_type_methods (type); - - stabstr_C (';'); - - if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE - /* Avoid the ~ if we don't really need it--it confuses dbx. */ - && TYPE_VFIELD (type)) - { - - /* We need to write out info about what field this class - uses as its "main" vtable pointer field, because if this - field is inherited from a base class, GDB cannot necessarily - figure out which field it's using in time. */ - stabstr_S ("~%"); - dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0); - stabstr_C (';'); - } - break; - - case ENUMERAL_TYPE: - /* We must use the same test here as we use in the DBX_NO_XREFS case - above. We simplify it a bit since an enum will never have a variable - size. */ - if ((TYPE_NAME (type) != 0 - && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_IGNORED_P (TYPE_NAME (type))) - && !full) - || !COMPLETE_TYPE_P (type)) - { - stabstr_S ("xe"); - dbxout_type_name (type); - typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; - stabstr_C (':'); - return; - } - if (use_gnu_debug_info_extensions - && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) - { - stabstr_S ("@s"); - stabstr_D (TYPE_PRECISION (type)); - stabstr_C (';'); - } - - stabstr_C ('e'); - for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) - { - tree value = TREE_VALUE (tem); - - stabstr_I (TREE_PURPOSE (tem)); - stabstr_C (':'); - - if (TREE_CODE (value) == CONST_DECL) - value = DECL_INITIAL (value); - - if (cst_and_fits_in_hwi (value)) - stabstr_D (TREE_INT_CST_LOW (value)); - else - stabstr_O (value); - - stabstr_C (','); - if (TREE_CHAIN (tem) != 0) - CONTIN; - } - - stabstr_C (';'); - break; - - case POINTER_TYPE: - stabstr_C ('*'); - dbxout_type (TREE_TYPE (type), 0); - break; - - case METHOD_TYPE: - if (use_gnu_debug_info_extensions) - { - stabstr_C ('#'); - - /* Write the argument types out longhand. */ - dbxout_type (TYPE_METHOD_BASETYPE (type), 0); - stabstr_C (','); - dbxout_type (TREE_TYPE (type), 0); - dbxout_args (TYPE_ARG_TYPES (type)); - stabstr_C (';'); - } - else - /* Treat it as a function type. */ - dbxout_type (TREE_TYPE (type), 0); - break; - - case OFFSET_TYPE: - if (use_gnu_debug_info_extensions) - { - stabstr_C ('@'); - dbxout_type (TYPE_OFFSET_BASETYPE (type), 0); - stabstr_C (','); - dbxout_type (TREE_TYPE (type), 0); - } - else - /* Should print as an int, because it is really just an offset. */ - dbxout_type (integer_type_node, 0); - break; - - case REFERENCE_TYPE: - if (use_gnu_debug_info_extensions) - { - stabstr_C ('&'); - } - else - stabstr_C ('*'); - dbxout_type (TREE_TYPE (type), 0); - break; - - case FUNCTION_TYPE: - stabstr_C ('f'); - dbxout_type (TREE_TYPE (type), 0); - break; - - default: - /* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM - named 'auto' in its type. - No debug info for TEMPLATE_TYPE_PARM type supported yet. */ - if (lang_GNU_CXX ()) - { - tree name = TYPE_IDENTIFIER (type); - if (name == get_identifier ("auto") - || name == get_identifier ("decltype(auto)")) - break; - } - - gcc_unreachable (); - } -} - -/* Return nonzero if the given type represents an integer whose bounds - should be printed in octal format. */ - -static bool -print_int_cst_bounds_in_octal_p (tree type, tree low, tree high) -{ - /* If we can use GDB extensions and the size is wider than a long - (the size used by GDB to read them) or we may have trouble writing - the bounds the usual way, write them in octal. Note the test is for - the *target's* size of "long", not that of the host. The host test - is just to make sure we can write it out in case the host wide int - is narrower than the target "long". - - For unsigned types, we use octal if they are the same size or larger. - This is because we print the bounds as signed decimal, and hence they - can't span same size unsigned types. */ - - if (use_gnu_debug_info_extensions - && low && TREE_CODE (low) == INTEGER_CST - && high && TREE_CODE (high) == INTEGER_CST - && (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node) - || ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) - && TYPE_UNSIGNED (type)) - || TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT - || (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT - && TYPE_UNSIGNED (type)))) - return TRUE; - else - return FALSE; -} - -/* Output the name of type TYPE, with no punctuation. - Such names can be set up either by typedef declarations - or by struct, enum and union tags. */ - -static void -dbxout_type_name (tree type) -{ - tree t = TYPE_NAME (type); - - gcc_assert (t); - switch (TREE_CODE (t)) - { - case IDENTIFIER_NODE: - break; - case TYPE_DECL: - t = DECL_NAME (t); - break; - default: - gcc_unreachable (); - } - - stabstr_I (t); -} - -/* Output leading struct or class names needed for qualifying type - whose scope is limited to a struct or class. */ - -static void -dbxout_class_name_qualifiers (tree decl) -{ - tree context = decl_type_context (decl); - - if (context != NULL_TREE - && TREE_CODE (context) == RECORD_TYPE - && TYPE_NAME (context) != 0 - && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE - || (DECL_NAME (TYPE_NAME (context)) != 0))) - { - tree name = TYPE_NAME (context); - - if (TREE_CODE (name) == TYPE_DECL) - { - dbxout_class_name_qualifiers (name); - name = DECL_NAME (name); - } - stabstr_I (name); - stabstr_S ("::"); - } -} - -/* This is a specialized subset of expand_expr for use by dbxout_symbol in - evaluating DECL_VALUE_EXPR. In particular, we stop if we find decls that - haven't been expanded, or if the expression is getting so complex we won't - be able to represent it in stabs anyway. Returns NULL on failure. */ - -static rtx -dbxout_expand_expr (tree expr) -{ - switch (TREE_CODE (expr)) - { - case VAR_DECL: - /* We can't handle emulated tls variables, because the address is an - offset to the return value of __emutls_get_address, and there is no - way to express that in stabs. Also, there are name mangling issues - here. We end up with references to undefined symbols if we don't - disable debug info for these variables. */ - if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr)) - return NULL; - if (TREE_STATIC (expr) - && !TREE_ASM_WRITTEN (expr) - && !DECL_HAS_VALUE_EXPR_P (expr) - && !TREE_PUBLIC (expr) - && DECL_RTL_SET_P (expr) - && MEM_P (DECL_RTL (expr))) - { - /* If this is a var that might not be actually output, - return NULL, otherwise stabs might reference an undefined - symbol. */ - varpool_node *node = varpool_node::get (expr); - if (!node || !node->definition) - return NULL; - } - /* FALLTHRU */ - - case PARM_DECL: - case RESULT_DECL: - if (DECL_HAS_VALUE_EXPR_P (expr)) - return dbxout_expand_expr (DECL_VALUE_EXPR (expr)); - /* FALLTHRU */ - - case CONST_DECL: - return DECL_RTL_IF_SET (expr); - - case INTEGER_CST: - return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); - - case COMPONENT_REF: - case ARRAY_REF: - case ARRAY_RANGE_REF: - case BIT_FIELD_REF: - { - machine_mode mode; - poly_int64 bitsize, bitpos; - tree offset, tem; - int unsignedp, reversep, volatilep = 0; - rtx x; - - tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode, - &unsignedp, &reversep, &volatilep); - - x = dbxout_expand_expr (tem); - if (x == NULL || !MEM_P (x)) - return NULL; - if (offset != NULL) - { - if (!tree_fits_shwi_p (offset)) - return NULL; - x = adjust_address_nv (x, mode, tree_to_shwi (offset)); - } - if (maybe_ne (bitpos, 0)) - x = adjust_address_nv (x, mode, bits_to_bytes_round_down (bitpos)); - - return x; - } - - default: - return NULL; - } -} - -/* Helper function for output_used_types. Queue one entry from the - used types hash to be output. */ - -bool -output_used_types_helper (tree const &type, vec<tree> *types_p) -{ - if ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && TYPE_STUB_DECL (type) - && DECL_P (TYPE_STUB_DECL (type)) - && ! DECL_IGNORED_P (TYPE_STUB_DECL (type))) - types_p->quick_push (TYPE_STUB_DECL (type)); - else if (TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) - types_p->quick_push (TYPE_NAME (type)); - - return true; -} - -/* This is a qsort callback which sorts types and declarations into a - predictable order (types, then declarations, sorted by UID - within). */ - -static int -output_types_sort (const void *pa, const void *pb) -{ - const tree lhs = *((const tree *)pa); - const tree rhs = *((const tree *)pb); - - if (TYPE_P (lhs)) - { - if (TYPE_P (rhs)) - return TYPE_UID (lhs) - TYPE_UID (rhs); - else - return 1; - } - else - { - if (TYPE_P (rhs)) - return -1; - else - return DECL_UID (lhs) - DECL_UID (rhs); - } -} - - -/* Force all types used by this function to be output in debug - information. */ - -static void -output_used_types (void) -{ - if (cfun && cfun->used_types_hash) - { - vec<tree> types; - int i; - tree type; - - types.create (cfun->used_types_hash->elements ()); - cfun->used_types_hash->traverse<vec<tree> *, output_used_types_helper> - (&types); - - /* Sort by UID to prevent dependence on hash table ordering. */ - types.qsort (output_types_sort); - - FOR_EACH_VEC_ELT (types, i, type) - debug_queue_symbol (type); - - types.release (); - } -} - -/* Output a .stabs for the symbol defined by DECL, - which must be a ..._DECL node in the normal namespace. - It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL. - LOCAL is nonzero if the scope is less than the entire file. - Return 1 if a stabs might have been emitted. */ - -int -dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED) -{ - tree type = TREE_TYPE (decl); - tree context = NULL_TREE; - int result = 0; - rtx decl_rtl; - - /* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */ - ++debug_nesting; - - /* Ignore nameless syms, but don't ignore type tags. */ - - if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) - || DECL_IGNORED_P (decl)) - DBXOUT_DECR_NESTING_AND_RETURN (0); - - /* If we are to generate only the symbols actually used then such - symbol nodes are flagged with TREE_USED. Ignore any that - aren't flagged as TREE_USED. */ - - if (flag_debug_only_used_symbols - && (!TREE_USED (decl) - && (!VAR_P (decl) || !DECL_INITIAL (decl)))) - DBXOUT_DECR_NESTING_AND_RETURN (0); - - /* If dbxout_init has not yet run, queue this symbol for later. */ - if (!typevec) - { - preinit_symbols = tree_cons (0, decl, preinit_symbols); - DBXOUT_DECR_NESTING_AND_RETURN (0); - } - - if (flag_debug_only_used_symbols) - { - tree t; - - /* We now have a used symbol. We need to generate the info for - the symbol's type in addition to the symbol itself. These - type symbols are queued to be generated after were done with - the symbol itself (otherwise they would fight over the - stabstr obstack). - - Note, because the TREE_TYPE(type) might be something like a - pointer to a named type we need to look for the first name - we see following the TREE_TYPE chain. */ - - t = type; - while (POINTER_TYPE_P (t)) - t = TREE_TYPE (t); - - /* RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, and ENUMERAL_TYPE - need special treatment. The TYPE_STUB_DECL field in these - types generally represents the tag name type we want to - output. In addition there could be a typedef type with - a different name. In that case we also want to output - that. */ - - if (TREE_CODE (t) == RECORD_TYPE - || TREE_CODE (t) == UNION_TYPE - || TREE_CODE (t) == QUAL_UNION_TYPE - || TREE_CODE (t) == ENUMERAL_TYPE) - { - if (TYPE_STUB_DECL (t) - && TYPE_STUB_DECL (t) != decl - && DECL_P (TYPE_STUB_DECL (t)) - && ! DECL_IGNORED_P (TYPE_STUB_DECL (t))) - { - debug_queue_symbol (TYPE_STUB_DECL (t)); - if (TYPE_NAME (t) - && TYPE_NAME (t) != TYPE_STUB_DECL (t) - && TYPE_NAME (t) != decl - && DECL_P (TYPE_NAME (t))) - debug_queue_symbol (TYPE_NAME (t)); - } - } - else if (TYPE_NAME (t) - && TYPE_NAME (t) != decl - && DECL_P (TYPE_NAME (t))) - debug_queue_symbol (TYPE_NAME (t)); - } - - emit_pending_bincls_if_required (); - - switch (TREE_CODE (decl)) - { - case CONST_DECL: - /* Enum values are defined by defining the enum type. */ - break; - - case FUNCTION_DECL: - decl_rtl = DECL_RTL_IF_SET (decl); - if (!decl_rtl) - DBXOUT_DECR_NESTING_AND_RETURN (0); - if (DECL_EXTERNAL (decl)) - break; - /* Don't mention a nested function under its parent. */ - context = decl_function_context (decl); - if (context == current_function_decl) - break; - /* Don't mention an inline instance of a nested function. */ - if (context && DECL_FROM_INLINE (decl)) - break; - if (!MEM_P (decl_rtl) - || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF) - break; - - if (flag_debug_only_used_symbols) - output_used_types (); - - dbxout_begin_complex_stabs (); - stabstr_I (DECL_ASSEMBLER_NAME (decl)); - stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f"); - result = 1; - - if (TREE_TYPE (type)) - dbxout_type (TREE_TYPE (type), 0); - else - dbxout_type (void_type_node, 0); - - /* For a nested function, when that function is compiled, - mention the containing function name - as well as (since dbx wants it) our own assembler-name. */ - if (context != 0) - { - stabstr_C (','); - stabstr_I (DECL_ASSEMBLER_NAME (decl)); - stabstr_C (','); - stabstr_I (DECL_NAME (context)); - } - - dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0); - break; - - case TYPE_DECL: - /* Don't output the same typedef twice. - And don't output what language-specific stuff doesn't want output. */ - if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl)) - DBXOUT_DECR_NESTING_AND_RETURN (0); - - /* Don't output typedefs for types with magic type numbers (XCOFF). */ -#ifdef DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER - { - int fundamental_type_number = - DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER (decl); - - if (fundamental_type_number != 0) - { - TREE_ASM_WRITTEN (decl) = 1; - TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = fundamental_type_number; - DBXOUT_DECR_NESTING_AND_RETURN (0); - } - } -#endif - FORCE_TEXT; - result = 1; - { - int tag_needed = 1; - int did_output = 0; - - if (DECL_NAME (decl)) - { - /* Nonzero means we must output a tag as well as a typedef. */ - tag_needed = 0; - - /* Handle the case of a C++ structure or union - where the TYPE_NAME is a TYPE_DECL - which gives both a typedef name and a tag. */ - /* dbx requires the tag first and the typedef second. */ - if ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE) - && TYPE_NAME (type) == decl - && !use_gnu_debug_info_extensions - && !TREE_ASM_WRITTEN (TYPE_NAME (type)) - /* Distinguish the implicit typedefs of C++ - from explicit ones that might be found in C. */ - && DECL_ARTIFICIAL (decl) - /* Do not generate a tag for incomplete records. */ - && COMPLETE_TYPE_P (type) - /* Do not generate a tag for records of variable size, - since this type cannot be properly described in the - DBX format, and it confuses some tools such as objdump. */ - && tree_fits_uhwi_p (TYPE_SIZE (type))) - { - tree name = TYPE_IDENTIFIER (type); - - dbxout_begin_complex_stabs (); - stabstr_I (name); - stabstr_S (":T"); - dbxout_type (type, 1); - dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, - 0, 0, 0); - } - - dbxout_begin_complex_stabs (); - - /* Output leading class/struct qualifiers. */ - if (use_gnu_debug_info_extensions) - dbxout_class_name_qualifiers (decl); - - /* Output typedef name. */ - stabstr_I (DECL_NAME (decl)); - stabstr_C (':'); - - /* Short cut way to output a tag also. */ - if ((TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == QUAL_UNION_TYPE) - && TYPE_NAME (type) == decl - /* Distinguish the implicit typedefs of C++ - from explicit ones that might be found in C. */ - && DECL_ARTIFICIAL (decl)) - { - if (use_gnu_debug_info_extensions) - { - stabstr_C ('T'); - TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1; - } - } - - stabstr_C ('t'); - dbxout_type (type, 1); - dbxout_finish_complex_stabs (decl, DBX_TYPE_DECL_STABS_CODE, - 0, 0, 0); - did_output = 1; - } - - /* Don't output a tag if this is an incomplete type. This prevents - the sun4 Sun OS 4.x dbx from crashing. */ - - if (tag_needed && TYPE_NAME (type) != 0 - && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE - || (DECL_NAME (TYPE_NAME (type)) != 0)) - && COMPLETE_TYPE_P (type) - && !TREE_ASM_WRITTEN (TYPE_NAME (type))) - { - /* For a TYPE_DECL with no name, but the type has a name, - output a tag. - This is what represents `struct foo' with no typedef. */ - /* In C++, the name of a type is the corresponding typedef. - In C, it is an IDENTIFIER_NODE. */ - tree name = TYPE_IDENTIFIER (type); - - dbxout_begin_complex_stabs (); - stabstr_I (name); - stabstr_S (":T"); - dbxout_type (type, 1); - dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0); - did_output = 1; - } - - /* If an enum type has no name, it cannot be referred to, but - we must output it anyway, to record the enumeration - constants. */ - - if (!did_output && TREE_CODE (type) == ENUMERAL_TYPE) - { - dbxout_begin_complex_stabs (); - /* Some debuggers fail when given NULL names, so give this a - harmless name of " " (Why not "(anon)"?). */ - stabstr_S (" :T"); - dbxout_type (type, 1); - dbxout_finish_complex_stabs (0, DBX_TYPE_DECL_STABS_CODE, 0, 0, 0); - } - - /* Prevent duplicate output of a typedef. */ - TREE_ASM_WRITTEN (decl) = 1; - break; - } - - case PARM_DECL: - if (DECL_HAS_VALUE_EXPR_P (decl)) - decl = DECL_VALUE_EXPR (decl); - - /* PARM_DECLs go in their own separate chain and are output by - dbxout_reg_parms and dbxout_parms, except for those that are - disguised VAR_DECLs like Out parameters in Ada. */ - gcc_assert (VAR_P (decl)); - - /* fall through */ - - case RESULT_DECL: - case VAR_DECL: - /* Don't mention a variable that is external. - Let the file that defines it describe it. */ - if (DECL_EXTERNAL (decl)) - break; - - /* If the variable is really a constant - and not written in memory, inform the debugger. - - ??? Why do we skip emitting the type and location in this case? */ - if (TREE_STATIC (decl) && TREE_READONLY (decl) - && DECL_INITIAL (decl) != 0 - && tree_fits_shwi_p (DECL_INITIAL (decl)) - && ! TREE_ASM_WRITTEN (decl) - && (DECL_FILE_SCOPE_P (decl) - || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK - || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL) - && TREE_PUBLIC (decl) == 0) - { - /* The sun4 assembler does not grok this. */ - - if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE - || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) - { - HOST_WIDE_INT ival = tree_to_shwi (DECL_INITIAL (decl)); - - dbxout_begin_complex_stabs (); - dbxout_symbol_name (decl, NULL, 'c'); - stabstr_S ("=i"); - stabstr_D (ival); - dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0); - DBXOUT_DECR_NESTING; - return 1; - } - else - break; - } - /* else it is something we handle like a normal variable. */ - - decl_rtl = dbxout_expand_expr (decl); - if (!decl_rtl) - DBXOUT_DECR_NESTING_AND_RETURN (0); - - if (!is_global_var (decl)) - decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX); -#ifdef LEAF_REG_REMAP - if (crtl->uses_only_leaf_regs) - leaf_renumber_regs_insn (decl_rtl); -#endif - - result = dbxout_symbol_location (decl, type, 0, decl_rtl); - break; - - default: - break; - } - DBXOUT_DECR_NESTING; - return result; -} - -/* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL. - Add SUFFIX to its name, if SUFFIX is not 0. - Describe the variable as residing in HOME - (usually HOME is DECL_RTL (DECL), but not always). - Returns 1 if the stab was really emitted. */ - -static int -dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home) -{ - int letter = 0; - stab_code_type code; - rtx addr = 0; - int number = 0; - int regno = -1; - - /* Don't mention a variable at all - if it was completely optimized into nothingness. - - If the decl was from an inline function, then its rtl - is not identically the rtl that was used in this - particular compilation. */ - if (GET_CODE (home) == SUBREG) - { - rtx value = home; - - while (GET_CODE (value) == SUBREG) - value = SUBREG_REG (value); - if (REG_P (value)) - { - if (REGNO (value) >= FIRST_PSEUDO_REGISTER) - return 0; - } - home = alter_subreg (&home, true); - } - if (REG_P (home)) - { - regno = REGNO (home); - if (regno >= FIRST_PSEUDO_REGISTER) - return 0; - } - - /* The kind-of-variable letter depends on where - the variable is and on the scope of its name: - G and N_GSYM for static storage and global scope, - S for static storage and file scope, - V for static storage and local scope, - for those two, use N_LCSYM if data is in bss segment, - N_STSYM if in data segment, N_FUN otherwise. - (We used N_FUN originally, then changed to N_STSYM - to please GDB. However, it seems that confused ld. - Now GDB has been fixed to like N_FUN, says Kingdon.) - no letter at all, and N_LSYM, for auto variable, - r and N_RSYM for register variable. */ - - if (MEM_P (home) && GET_CODE (XEXP (home, 0)) == SYMBOL_REF) - { - if (TREE_PUBLIC (decl)) - { - int offs; - letter = 'G'; - code = N_GSYM; - if (dbxout_common_check (decl, &offs) != NULL) - { - letter = 'V'; - addr = 0; - number = offs; - } - } - else - { - addr = XEXP (home, 0); - - letter = decl_function_context (decl) ? 'V' : 'S'; - - /* Some ports can transform a symbol ref into a label ref, - because the symbol ref is too far away and has to be - dumped into a constant pool. Alternatively, the symbol - in the constant pool might be referenced by a different - symbol. */ - if (GET_CODE (addr) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (addr)) - { - bool marked; - rtx tmp = get_pool_constant_mark (addr, &marked); - - if (GET_CODE (tmp) == SYMBOL_REF) - { - addr = tmp; - if (CONSTANT_POOL_ADDRESS_P (addr)) - get_pool_constant_mark (addr, &marked); - else - marked = true; - } - else if (GET_CODE (tmp) == LABEL_REF) - { - addr = tmp; - marked = true; - } - - /* If all references to the constant pool were optimized - out, we just ignore the symbol. */ - if (!marked) - return 0; - } - - /* This should be the same condition as in assemble_variable, but - we don't have access to dont_output_data here. So, instead, - we rely on the fact that error_mark_node initializers always - end up in bss for C++ and never end up in bss for C. */ - if (DECL_INITIAL (decl) == 0 - || (lang_GNU_CXX () - && DECL_INITIAL (decl) == error_mark_node)) - { - int offs; - code = N_LCSYM; - if (dbxout_common_check (decl, &offs) != NULL) - { - addr = 0; - number = offs; - letter = 'V'; - code = N_GSYM; - } - } - else if (DECL_IN_TEXT_SECTION (decl)) - /* This is not quite right, but it's the closest - of all the codes that Unix defines. */ - code = DBX_STATIC_CONST_VAR_CODE; - else - { - /* Ultrix `as' seems to need this. */ -#ifdef DBX_STATIC_STAB_DATA_SECTION - switch_to_section (data_section); -#endif - code = N_STSYM; - } - } - } - else if (regno >= 0) - { - letter = 'r'; - code = N_RSYM; - number = DBX_REGISTER_NUMBER (regno); - } - else if (MEM_P (home) - && (MEM_P (XEXP (home, 0)) - || (REG_P (XEXP (home, 0)) - && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM - && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM -#if !HARD_FRAME_POINTER_IS_ARG_POINTER - && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM -#endif - ))) - /* If the value is indirect by memory or by a register - that isn't the frame pointer - then it means the object is variable-sized and address through - that register or stack slot. DBX has no way to represent this - so all we can do is output the variable as a pointer. - If it's not a parameter, ignore it. */ - { - if (REG_P (XEXP (home, 0))) - { - letter = 'r'; - code = N_RSYM; - if (REGNO (XEXP (home, 0)) >= FIRST_PSEUDO_REGISTER) - return 0; - number = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0))); - } - else - { - code = N_LSYM; - /* RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))). - We want the value of that CONST_INT. */ - number = DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0)); - } - - /* Effectively do build_pointer_type, but don't cache this type, - since it might be temporary whereas the type it points to - might have been saved for inlining. */ - /* Don't use REFERENCE_TYPE because dbx can't handle that. */ - type = make_node (POINTER_TYPE); - TREE_TYPE (type) = TREE_TYPE (decl); - } - else if (MEM_P (home) - && REG_P (XEXP (home, 0))) - { - code = N_LSYM; - number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0)); - } - else if (MEM_P (home) - && GET_CODE (XEXP (home, 0)) == PLUS - && CONST_INT_P (XEXP (XEXP (home, 0), 1))) - { - code = N_LSYM; - /* RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) - We want the value of that CONST_INT. */ - number = DEBUGGER_AUTO_OFFSET (XEXP (home, 0)); - } - else if (MEM_P (home) - && GET_CODE (XEXP (home, 0)) == CONST) - { - /* Handle an obscure case which can arise when optimizing and - when there are few available registers. (This is *always* - the case for i386/i486 targets). The RTL looks like - (MEM (CONST ...)) even though this variable is a local `auto' - or a local `register' variable. In effect, what has happened - is that the reload pass has seen that all assignments and - references for one such a local variable can be replaced by - equivalent assignments and references to some static storage - variable, thereby avoiding the need for a register. In such - cases we're forced to lie to debuggers and tell them that - this variable was itself `static'. */ - int offs; - code = N_LCSYM; - letter = 'V'; - if (dbxout_common_check (decl, &offs) == NULL) - addr = XEXP (XEXP (home, 0), 0); - else - { - addr = 0; - number = offs; - code = N_GSYM; - } - } - else if (GET_CODE (home) == CONCAT) - { - tree subtype; - - /* If TYPE is not a COMPLEX_TYPE (it might be a RECORD_TYPE, - for example), then there is no easy way to figure out - what SUBTYPE should be. So, we give up. */ - if (TREE_CODE (type) != COMPLEX_TYPE) - return 0; - - subtype = TREE_TYPE (type); - - /* If the variable's storage is in two parts, - output each as a separate stab with a modified name. */ - if (WORDS_BIG_ENDIAN) - dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 0)); - else - dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0)); - - if (WORDS_BIG_ENDIAN) - dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1)); - else - dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1)); - return 1; - } - else - /* Address might be a MEM, when DECL is a variable-sized object. - Or it might be const0_rtx, meaning previous passes - want us to ignore this variable. */ - return 0; - - /* Ok, start a symtab entry and output the variable name. */ - emit_pending_bincls_if_required (); - FORCE_TEXT; - -#ifdef DBX_STATIC_BLOCK_START - DBX_STATIC_BLOCK_START (asm_out_file, code); -#endif - - dbxout_begin_complex_stabs_noforcetext (); - dbxout_symbol_name (decl, suffix, letter); - dbxout_type (type, 0); - dbxout_finish_complex_stabs (decl, code, addr, 0, number); - -#ifdef DBX_STATIC_BLOCK_END - DBX_STATIC_BLOCK_END (asm_out_file, code); -#endif - return 1; -} - -/* Output the symbol name of DECL for a stabs, with suffix SUFFIX. - Then output LETTER to indicate the kind of location the symbol has. */ - -static void -dbxout_symbol_name (tree decl, const char *suffix, int letter) -{ - tree name; - - if (DECL_CONTEXT (decl) - && (TYPE_P (DECL_CONTEXT (decl)) - || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)) - /* One slight hitch: if this is a VAR_DECL which is a class member - or a namespace member, we must put out the mangled name instead of the - DECL_NAME. Note also that static member (variable) names DO NOT begin - with underscores in .stabs directives. */ - name = DECL_ASSEMBLER_NAME (decl); - else - /* ...but if we're function-local, we don't want to include the junk - added by ASM_FORMAT_PRIVATE_NAME. */ - name = DECL_NAME (decl); - - if (name) - stabstr_I (name); - else - stabstr_S ("(anon)"); - - if (suffix) - stabstr_S (suffix); - stabstr_C (':'); - if (letter) - stabstr_C (letter); -} - - -/* Output the common block name for DECL in a stabs. - - Symbols in global common (.comm) get wrapped with an N_BCOMM/N_ECOMM pair - around each group of symbols in the same .comm area. The N_GSYM stabs - that are emitted only contain the offset in the common area. This routine - emits the N_BCOMM and N_ECOMM stabs. */ - -static void -dbxout_common_name (tree decl, const char *name, stab_code_type op) -{ - dbxout_begin_complex_stabs (); - stabstr_S (name); - dbxout_finish_complex_stabs (decl, op, NULL_RTX, NULL, 0); -} - -/* Check decl to determine whether it is a VAR_DECL destined for storage in a - common area. If it is, the return value will be a non-null string giving - the name of the common storage block it will go into. If non-null, the - value is the offset into the common block for that symbol's storage. */ - -static const char * -dbxout_common_check (tree decl, int *value) -{ - rtx home; - rtx sym_addr; - const char *name = NULL; - - /* If the decl isn't a VAR_DECL, or if it isn't static, or if - it does not have a value (the offset into the common area), or if it - is thread local (as opposed to global) then it isn't common, and shouldn't - be handled as such. - - ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs - for thread-local symbols. Can be handled via same mechanism as used - in dwarf2out.cc. */ - if (!VAR_P (decl) - || !TREE_STATIC (decl) - || !DECL_HAS_VALUE_EXPR_P (decl) - || DECL_THREAD_LOCAL_P (decl) - || !is_fortran ()) - return NULL; - - home = DECL_RTL (decl); - if (home == NULL_RTX || GET_CODE (home) != MEM) - return NULL; - - sym_addr = dbxout_expand_expr (DECL_VALUE_EXPR (decl)); - if (sym_addr == NULL_RTX || GET_CODE (sym_addr) != MEM) - return NULL; - - sym_addr = XEXP (sym_addr, 0); - if (GET_CODE (sym_addr) == CONST) - sym_addr = XEXP (sym_addr, 0); - if ((GET_CODE (sym_addr) == SYMBOL_REF || GET_CODE (sym_addr) == PLUS) - && DECL_INITIAL (decl) == 0) - { - - /* We have a sym that will go into a common area, meaning that it - will get storage reserved with a .comm/.lcomm assembler pseudo-op. - - Determine name of common area this symbol will be an offset into, - and offset into that area. Also retrieve the decl for the area - that the symbol is offset into. */ - tree cdecl = NULL; - - switch (GET_CODE (sym_addr)) - { - case PLUS: - if (CONST_INT_P (XEXP (sym_addr, 0))) - { - name = - targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 1), 0)); - *value = INTVAL (XEXP (sym_addr, 0)); - cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1)); - } - else - { - name = - targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 0), 0)); - *value = INTVAL (XEXP (sym_addr, 1)); - cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0)); - } - break; - - case SYMBOL_REF: - name = targetm.strip_name_encoding (XSTR (sym_addr, 0)); - *value = 0; - cdecl = SYMBOL_REF_DECL (sym_addr); - break; - - default: - error ("common symbol debug info is not structured as " - "symbol+offset"); - } - - /* Check area common symbol is offset into. If this is not public, then - it is not a symbol in a common block. It must be a .lcomm symbol, not - a .comm symbol. */ - if (cdecl == NULL || !TREE_PUBLIC (cdecl)) - name = NULL; - } - else - name = NULL; - - return name; -} - -/* Output definitions of all the decls in a chain. Return nonzero if - anything was output */ - -int -dbxout_syms (tree syms) -{ - int result = 0; - const char *comm_prev = NULL; - tree syms_prev = NULL; - - while (syms) - { - int temp, copen, cclos; - const char *comm_new; - - /* Check for common symbol, and then progression into a new/different - block of common symbols. Emit closing/opening common bracket if - necessary. */ - comm_new = dbxout_common_check (syms, &temp); - copen = comm_new != NULL - && (comm_prev == NULL || strcmp (comm_new, comm_prev)); - cclos = comm_prev != NULL - && (comm_new == NULL || strcmp (comm_new, comm_prev)); - if (cclos) - dbxout_common_name (syms_prev, comm_prev, N_ECOMM); - if (copen) - { - dbxout_common_name (syms, comm_new, N_BCOMM); - syms_prev = syms; - } - comm_prev = comm_new; - - result += dbxout_symbol (syms, 1); - syms = DECL_CHAIN (syms); - } - - if (comm_prev != NULL) - dbxout_common_name (syms_prev, comm_prev, N_ECOMM); - - return result; -} - -/* The following two functions output definitions of function parameters. - Each parameter gets a definition locating it in the parameter list. - Each parameter that is a register variable gets a second definition - locating it in the register. - - Printing or argument lists in gdb uses the definitions that - locate in the parameter list. But reference to the variable in - expressions uses preferentially the definition as a register. */ - -/* Output definitions, referring to storage in the parmlist, - of all the parms in PARMS, which is a chain of PARM_DECL nodes. */ - -void -dbxout_parms (tree parms) -{ - ++debug_nesting; - emit_pending_bincls_if_required (); - fixed_size_mode rtl_mode, type_mode; - - for (; parms; parms = DECL_CHAIN (parms)) - if (DECL_NAME (parms) - && TREE_TYPE (parms) != error_mark_node - && DECL_RTL_SET_P (parms) - && DECL_INCOMING_RTL (parms) - /* We can't represent variable-sized types in this format. */ - && is_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (parms)), &type_mode) - && is_a <fixed_size_mode> (GET_MODE (DECL_RTL (parms)), &rtl_mode)) - { - tree eff_type; - char letter; - stab_code_type code; - int number; - - /* Perform any necessary register eliminations on the parameter's rtl, - so that the debugging output will be accurate. */ - DECL_INCOMING_RTL (parms) - = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX); - SET_DECL_RTL (parms, - eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX)); -#ifdef LEAF_REG_REMAP - if (crtl->uses_only_leaf_regs) - { - leaf_renumber_regs_insn (DECL_INCOMING_RTL (parms)); - leaf_renumber_regs_insn (DECL_RTL (parms)); - } -#endif - - if (PARM_PASSED_IN_MEMORY (parms)) - { - rtx inrtl = XEXP (DECL_INCOMING_RTL (parms), 0); - - /* ??? Here we assume that the parm address is indexed - off the frame pointer or arg pointer. - If that is not true, we produce meaningless results, - but do not crash. */ - if (GET_CODE (inrtl) == PLUS - && CONST_INT_P (XEXP (inrtl, 1))) - number = INTVAL (XEXP (inrtl, 1)); - else - number = 0; - - code = N_PSYM; - number = DEBUGGER_ARG_OFFSET (number, inrtl); - letter = 'p'; - - /* It is quite tempting to use TREE_TYPE (parms) instead - of DECL_ARG_TYPE (parms) for the eff_type, so that gcc - reports the actual type of the parameter, rather than - the promoted type. This certainly makes GDB's life - easier, at least for some ports. The change is a bad - idea however, since GDB expects to be able access the - type without performing any conversions. So for - example, if we were passing a float to an unprototyped - function, gcc will store a double on the stack, but if - we emit a stab saying the type is a float, then gdb - will only read in a single value, and this will produce - an erroneous value. */ - eff_type = DECL_ARG_TYPE (parms); - } - else if (REG_P (DECL_RTL (parms))) - { - rtx best_rtl; - - /* Parm passed in registers and lives in registers or nowhere. */ - code = DBX_REGPARM_STABS_CODE; - letter = DBX_REGPARM_STABS_LETTER; - - /* For parms passed in registers, it is better to use the - declared type of the variable, not the type it arrived in. */ - eff_type = TREE_TYPE (parms); - - /* If parm lives in a register, use that register; pretend - the parm was passed there. It would be more consistent - to describe the register where the parm was passed, but - in practice that register usually holds something else. - If the parm lives nowhere, use the register where it - was passed. */ - if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) - best_rtl = DECL_RTL (parms); - else if (GET_CODE (DECL_INCOMING_RTL (parms)) == PARALLEL) - best_rtl = XEXP (XVECEXP (DECL_INCOMING_RTL (parms), 0, 0), 0); - else - best_rtl = DECL_INCOMING_RTL (parms); - - number = DBX_REGISTER_NUMBER (REGNO (best_rtl)); - } - else if (MEM_P (DECL_RTL (parms)) - && REG_P (XEXP (DECL_RTL (parms), 0)) - && REGNO (XEXP (DECL_RTL (parms), 0)) != HARD_FRAME_POINTER_REGNUM - && REGNO (XEXP (DECL_RTL (parms), 0)) != STACK_POINTER_REGNUM -#if !HARD_FRAME_POINTER_IS_ARG_POINTER - && REGNO (XEXP (DECL_RTL (parms), 0)) != ARG_POINTER_REGNUM -#endif - ) - { - /* Parm was passed via invisible reference. - That is, its address was passed in a register. - Output it as if it lived in that register. - The debugger will know from the type - that it was actually passed by invisible reference. */ - - code = DBX_REGPARM_STABS_CODE; - - /* GDB likes this marked with a special letter. */ - letter = (use_gnu_debug_info_extensions - ? 'a' : DBX_REGPARM_STABS_LETTER); - eff_type = TREE_TYPE (parms); - - /* DECL_RTL looks like (MEM (REG...). Get the register number. - If it is an unallocated pseudo-reg, then use the register where - it was passed instead. - ??? Why is DBX_REGISTER_NUMBER not used here? */ - - if (REGNO (XEXP (DECL_RTL (parms), 0)) < FIRST_PSEUDO_REGISTER) - number = REGNO (XEXP (DECL_RTL (parms), 0)); - else - number = REGNO (DECL_INCOMING_RTL (parms)); - } - else if (MEM_P (DECL_RTL (parms)) - && MEM_P (XEXP (DECL_RTL (parms), 0))) - { - /* Parm was passed via invisible reference, with the reference - living on the stack. DECL_RTL looks like - (MEM (MEM (PLUS (REG ...) (CONST_INT ...)))) or it - could look like (MEM (MEM (REG))). */ - - code = N_PSYM; - letter = 'v'; - eff_type = TREE_TYPE (parms); - - if (!REG_P (XEXP (XEXP (DECL_RTL (parms), 0), 0))) - number = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1)); - else - number = 0; - - number = DEBUGGER_ARG_OFFSET (number, - XEXP (XEXP (DECL_RTL (parms), 0), 0)); - } - else if (MEM_P (DECL_RTL (parms)) - && XEXP (DECL_RTL (parms), 0) != const0_rtx - /* ??? A constant address for a parm can happen - when the reg it lives in is equiv to a constant in memory. - Should make this not happen, after 2.4. */ - && ! CONSTANT_P (XEXP (DECL_RTL (parms), 0))) - { - /* Parm was passed in registers but lives on the stack. */ - - code = N_PSYM; - letter = 'p'; - eff_type = TREE_TYPE (parms); - - /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), - in which case we want the value of that CONST_INT, - or (MEM (REG ...)), - in which case we use a value of zero. */ - if (!REG_P (XEXP (DECL_RTL (parms), 0))) - number = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); - else - number = 0; - - /* Make a big endian correction if the mode of the type of the - parameter is not the same as the mode of the rtl. */ - if (BYTES_BIG_ENDIAN - && type_mode != rtl_mode - && GET_MODE_SIZE (type_mode) < UNITS_PER_WORD) - number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode); - } - else - /* ??? We don't know how to represent this argument. */ - continue; - - dbxout_begin_complex_stabs (); - - if (DECL_NAME (parms)) - { - stabstr_I (DECL_NAME (parms)); - stabstr_C (':'); - } - else - stabstr_S ("(anon):"); - stabstr_C (letter); - dbxout_type (eff_type, 0); - dbxout_finish_complex_stabs (parms, code, 0, 0, number); - } - DBXOUT_DECR_NESTING; -} - -/* Output definitions for the places where parms live during the function, - when different from where they were passed, when the parms were passed - in memory. - - It is not useful to do this for parms passed in registers - that live during the function in different registers, because it is - impossible to look in the passed register for the passed value, - so we use the within-the-function register to begin with. - - PARMS is a chain of PARM_DECL nodes. */ - -void -dbxout_reg_parms (tree parms) -{ - ++debug_nesting; - - for (; parms; parms = DECL_CHAIN (parms)) - if (DECL_NAME (parms) && PARM_PASSED_IN_MEMORY (parms)) - { - /* Report parms that live in registers during the function - but were passed in memory. */ - if (REG_P (DECL_RTL (parms)) - && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) - dbxout_symbol_location (parms, TREE_TYPE (parms), - 0, DECL_RTL (parms)); - else if (GET_CODE (DECL_RTL (parms)) == CONCAT) - dbxout_symbol_location (parms, TREE_TYPE (parms), - 0, DECL_RTL (parms)); - /* Report parms that live in memory but not where they were passed. */ - else if (MEM_P (DECL_RTL (parms)) - && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) - dbxout_symbol_location (parms, TREE_TYPE (parms), - 0, DECL_RTL (parms)); - } - DBXOUT_DECR_NESTING; -} - -/* Given a chain of ..._TYPE nodes (as come in a parameter list), - output definitions of those names, in raw form */ - -static void -dbxout_args (tree args) -{ - while (args) - { - stabstr_C (','); - dbxout_type (TREE_VALUE (args), 0); - args = TREE_CHAIN (args); - } -} - -#if defined (DBX_DEBUGGING_INFO) - -/* Subroutine of dbxout_block. Emit an N_LBRAC stab referencing LABEL. - BEGIN_LABEL is the name of the beginning of the function, which may - be required. */ -static void -dbx_output_lbrac (const char *label, - const char *begin_label ATTRIBUTE_UNUSED) -{ - dbxout_begin_stabn (N_LBRAC); - if (DBX_BLOCKS_FUNCTION_RELATIVE) - dbxout_stab_value_label_diff (label, begin_label); - else - dbxout_stab_value_label (label); -} - -/* Subroutine of dbxout_block. Emit an N_RBRAC stab referencing LABEL. - BEGIN_LABEL is the name of the beginning of the function, which may - be required. */ -static void -dbx_output_rbrac (const char *label, - const char *begin_label ATTRIBUTE_UNUSED) -{ - dbxout_begin_stabn (N_RBRAC); - if (DBX_BLOCKS_FUNCTION_RELATIVE) - dbxout_stab_value_label_diff (label, begin_label); - else - dbxout_stab_value_label (label); -} - -/* Return true if at least one block among BLOCK, its children or siblings - has TREE_USED, TREE_ASM_WRITTEN and BLOCK_IN_COLD_SECTION_P - set. If there is none, clear TREE_USED bit on such blocks. */ - -static bool -dbx_block_with_cold_children (tree block) -{ - bool ret = false; - for (; block; block = BLOCK_CHAIN (block)) - if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) - { - bool children = dbx_block_with_cold_children (BLOCK_SUBBLOCKS (block)); - if (BLOCK_IN_COLD_SECTION_P (block) || children) - ret = true; - else - TREE_USED (block) = false; - } - return ret; -} - -/* Output everything about a symbol block (a BLOCK node - that represents a scope level), - including recursive output of contained blocks. - - BLOCK is the BLOCK node. - DEPTH is its depth within containing symbol blocks. - ARGS is usually zero; but for the outermost block of the - body of a function, it is a chain of PARM_DECLs for the function parameters. - We output definitions of all the register parms - as if they were local variables of that block. - - If -g1 was used, we count blocks just the same, but output nothing - except for the outermost block. - - Actually, BLOCK may be several blocks chained together. - We handle them all in sequence. - - Return true if we emitted any LBRAC/RBRAC. */ - -static bool -dbxout_block (tree block, int depth, tree args, int parent_blocknum) -{ - bool ret = false; - char begin_label[20]; - /* Reference current function start using LFBB. */ - ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno); - - /* If called for the second partition, ignore blocks that don't have - any children in the second partition. */ - if (crtl->has_bb_partition && in_cold_section_p && depth == 0) - dbx_block_with_cold_children (block); - - for (; block; block = BLOCK_CHAIN (block)) - { - /* Ignore blocks never expanded or otherwise marked as real. */ - if (TREE_USED (block) && TREE_ASM_WRITTEN (block)) - { - int did_output; - int blocknum = BLOCK_NUMBER (block); - int this_parent = parent_blocknum; - - /* In dbx format, the syms of a block come before the N_LBRAC. - If nothing is output, we don't need the N_LBRAC, either. */ - did_output = 0; - if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0) - did_output = dbxout_syms (BLOCK_VARS (block)); - if (args) - dbxout_reg_parms (args); - - /* Now output an N_LBRAC symbol to represent the beginning of - the block. Use the block's tree-walk order to generate - the assembler symbols LBBn and LBEn - that final will define around the code in this block. */ - if (did_output - && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p) - { - char buf[20]; - const char *scope_start; - - ret = true; - if (depth == 0) - /* The outermost block doesn't get LBB labels; use - the LFBB local symbol emitted by dbxout_begin_prologue. */ - scope_start = begin_label; - else - { - ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum); - scope_start = buf; - this_parent = blocknum; - } - - dbx_output_lbrac (scope_start, begin_label); - } - - /* Output the subblocks. */ - bool children - = dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE, - this_parent); - ret |= children; - - /* Refer to the marker for the end of the block. */ - if (did_output - && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p) - { - char buf[100]; - if (depth == 0) - /* The outermost block doesn't get LBE labels; - use the "scope" label which will be emitted - by dbxout_function_end. */ - ASM_GENERATE_INTERNAL_LABEL (buf, "Lscope", scope_labelno); - else - ASM_GENERATE_INTERNAL_LABEL (buf, "LBE", blocknum); - - dbx_output_rbrac (buf, begin_label); - } - else if (did_output && !children) - { - /* If we emitted any vars and didn't output any LBRAC/RBRAC, - either at this level or any lower level, we need to emit - an empty LBRAC/RBRAC pair now. */ - char buf[30]; - const char *scope_start; - - ret = true; - if (parent_blocknum == -1) - scope_start = begin_label; - else - { - ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", parent_blocknum); - scope_start = buf; - } - - dbx_output_lbrac (scope_start, begin_label); - dbx_output_rbrac (scope_start, begin_label); - } - } - } - return ret; -} - -/* Output the information about a function and its arguments and result. - Usually this follows the function's code, - but on some systems, it comes before. */ - -static void -dbxout_begin_function (tree decl) -{ - int saved_tree_used1; - - saved_tree_used1 = TREE_USED (decl); - TREE_USED (decl) = 1; - if (DECL_NAME (DECL_RESULT (decl)) != 0) - { - int saved_tree_used2 = TREE_USED (DECL_RESULT (decl)); - TREE_USED (DECL_RESULT (decl)) = 1; - dbxout_symbol (decl, 0); - TREE_USED (DECL_RESULT (decl)) = saved_tree_used2; - } - else - dbxout_symbol (decl, 0); - TREE_USED (decl) = saved_tree_used1; - - dbxout_parms (DECL_ARGUMENTS (decl)); - if (DECL_NAME (DECL_RESULT (decl)) != 0) - dbxout_symbol (DECL_RESULT (decl), 1); -} -#endif /* DBX_DEBUGGING_INFO */ - -#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ - -/* Record an element in the table of global destructors. SYMBOL is - a SYMBOL_REF of the function to be called; PRIORITY is a number - between 0 and MAX_INIT_PRIORITY. */ - -void -default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED, - int priority ATTRIBUTE_UNUSED) -{ -#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO - /* Tell GNU LD that this is part of the static destructor set. - This will work for any system that uses stabs, most usefully - aout systems. */ - dbxout_begin_simple_stabs ("___DTOR_LIST__", 22 /* N_SETT */); - dbxout_stab_value_label (XSTR (symbol, 0)); -#else - sorry ("global destructors not supported on this target"); -#endif -} - -/* Likewise for global constructors. */ - -void -default_stabs_asm_out_constructor (rtx symbol ATTRIBUTE_UNUSED, - int priority ATTRIBUTE_UNUSED) -{ -#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO - /* Tell GNU LD that this is part of the static destructor set. - This will work for any system that uses stabs, most usefully - aout systems. */ - dbxout_begin_simple_stabs ("___CTOR_LIST__", 22 /* N_SETT */); - dbxout_stab_value_label (XSTR (symbol, 0)); -#else - sorry ("global constructors not supported on this target"); -#endif -} - -#include "gt-dbxout.h" diff --git a/gcc/dbxout.h b/gcc/dbxout.h deleted file mode 100644 index 2c38e76..0000000 --- a/gcc/dbxout.h +++ /dev/null @@ -1,60 +0,0 @@ -/* dbxout.h - Various declarations for functions found in dbxout.cc - Copyright (C) 1998-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#ifndef GCC_DBXOUT_H -#define GCC_DBXOUT_H - -extern int dbxout_symbol (tree, int); -extern void dbxout_parms (tree); -extern void dbxout_reg_parms (tree); -extern int dbxout_syms (tree); - -extern void default_stabs_asm_out_destructor (rtx, int); -extern void default_stabs_asm_out_constructor (rtx, int); - -/* dbxout helper functions */ -#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO - -extern void dbxout_int (int); -extern void dbxout_stabd (int, int); -extern void dbxout_begin_stabn (int); -extern void dbxout_begin_stabn_sline (int); -extern void dbxout_begin_empty_stabs (int); -extern void dbxout_begin_simple_stabs (const char *, int); -extern void dbxout_begin_simple_stabs_desc (const char *, int, int); - -extern void dbxout_stab_value_zero (void); -extern void dbxout_stab_value_label (const char *); -extern void dbxout_stab_value_label_diff (const char *, const char *); -extern void dbxout_stab_value_internal_label (const char *, int *); -extern void dbxout_stab_value_internal_label_diff (const char *, int *, - const char *); -#endif - -/* Language description for N_SO stabs. */ -#define N_SO_AS 1 -#define N_SO_C 2 -#define N_SO_ANSI_C 3 -#define N_SO_CC 4 /* c++*/ -#define N_SO_FORTRAN 5 -#define N_SO_FORTRAN90 7 -#define N_SO_OBJC 50 -#define N_SO_OBJCPLUS 51 - -#endif /* GCC_DBXOUT_H */ diff --git a/gcc/debug.h b/gcc/debug.h index 17a7e48..fe85115 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -238,7 +238,6 @@ extern void debug_nothing_tree_charstar_uhwi (tree, const char *, /* Hooks for various debug formats. */ extern const struct gcc_debug_hooks do_nothing_debug_hooks; -extern const struct gcc_debug_hooks dbx_debug_hooks; extern const struct gcc_debug_hooks xcoff_debug_hooks; extern const struct gcc_debug_hooks dwarf2_debug_hooks; extern const struct gcc_debug_hooks dwarf2_lineno_debug_hooks; diff --git a/gcc/defaults.h b/gcc/defaults.h index 7c7a80e..953605c 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -429,17 +429,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif #endif -/* How to renumber registers for dbx and gdb. If not defined, assume +/* How to renumber registers for gdb. If not defined, assume no renumbering is necessary. */ -#ifndef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(REGNO) (REGNO) +#ifndef DEBUGGER_REGNO +#define DEBUGGER_REGNO(REGNO) (REGNO) #endif /* The mapping from gcc register number to DWARF 2 CFA column number. By default, we just provide columns for all registers. */ #ifndef DWARF_FRAME_REGNUM -#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) +#define DWARF_FRAME_REGNUM(REG) DEBUGGER_REGNO (REG) #endif /* The mapping from dwarf CFA reg number to internal dwarf reg numbers. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index b54b972..d4d28f1 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2529,7 +2529,6 @@ GCC plugins may provide their own attributes. * AVR Function Attributes:: * Blackfin Function Attributes:: * BPF Function Attributes:: -* CR16 Function Attributes:: * C-SKY Function Attributes:: * Epiphany Function Attributes:: * H8/300 Function Attributes:: @@ -5083,20 +5082,6 @@ int bpf_probe_read (void *dst, int size, const void *unsafe_ptr) @end smallexample @end table -@node CR16 Function Attributes -@subsection CR16 Function Attributes - -These function attributes are supported by the CR16 back end: - -@table @code -@item interrupt -@cindex @code{interrupt} function attribute, CR16 -Use this attribute to indicate -that the specified function is an interrupt handler. The compiler generates -function entry and exit sequences suitable for use in an interrupt handler -when this attribute is present. -@end table - @node C-SKY Function Attributes @subsection C-SKY Function Attributes @@ -7309,6 +7294,7 @@ attributes. * Blackfin Variable Attributes:: * H8/300 Variable Attributes:: * IA-64 Variable Attributes:: +* LoongArch Variable Attributes:: * M32R/D Variable Attributes:: * MeP Variable Attributes:: * Microsoft Windows Variable Attributes:: @@ -8093,6 +8079,22 @@ defined by shared libraries. @end table +@node LoongArch Variable Attributes +@subsection LoongArch Variable Attributes + +One attribute is currently defined for the LoongArch. + +@table @code +@item model("@var{name}") +@cindex @code{model} variable attribute, LoongArch +Use this attribute on the LoongArch to use a different code model for +addressing this variable, than the code model specified by the global +@option{-mcmodel} option. This attribute is mostly useful if a +@code{section} attribute and/or a linker script will locate this object +specially. Currently the only supported values of @var{name} are +@code{normal} and @code{extreme}. +@end table + @node M32R/D Variable Attributes @subsection M32R/D Variable Attributes @@ -12996,6 +12998,7 @@ is called and the @var{flag} argument passed to it. @findex __builtin_isless @findex __builtin_islessequal @findex __builtin_islessgreater +@findex __builtin_issignaling @findex __builtin_isunordered @findex __builtin_object_size @findex __builtin_powi @@ -13551,6 +13554,8 @@ In the same fashion, GCC provides @code{fpclassify}, @code{isfinite}, @code{isinf_sign}, @code{isnormal} and @code{signbit} built-ins used with @code{__builtin_} prefixed. The @code{isinf} and @code{isnan} built-in functions appear both with and without the @code{__builtin_} prefix. +With @code{-ffinite-math-only} option the @code{isinf} and @code{isnan} +built-in functions will always return 0. GCC provides built-in versions of the ISO C99 floating-point rounding and exceptions handling functions @code{fegetround}, @code{feclearexcept} and @@ -14484,6 +14489,20 @@ Similar to @code{__builtin_nans}, except the return type is @code{_Float@var{n}x}. @end deftypefn +@deftypefn {Built-in Function} int __builtin_issignaling (...) +Return non-zero if the argument is a signaling NaN and zero otherwise. +Note while the parameter list is an +ellipsis, this function only accepts exactly one floating-point +argument. GCC treats this parameter as type-generic, which means it +does not do default promotion from float to double. +This built-in function can work even without the non-default +@code{-fsignaling-nans} option, although if a signaling NaN is computed, +stored or passed as argument to some function other than this built-in +in the current translation unit, it is safer to use @code{-fsignaling-nans}. +With @code{-ffinite-math-only} option this built-in function will always +return 0. +@end deftypefn + @deftypefn {Built-in Function} int __builtin_ffs (int x) Returns one plus the index of the least significant 1-bit of @var{x}, or if @var{x} is zero, returns zero. diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 5a4976f..0449dc1 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -743,7 +743,7 @@ Here are the possible CPU types: @quotation aarch64, aarch64_be, alpha, alpha64, amdgcn, arc, arceb, arm, armeb, avr, bfin, -bpf, cr16, cris, csky, epiphany, fido, fr30, frv, ft32, h8300, hppa, hppa2.0, +bpf, cris, csky, epiphany, fido, fr30, frv, ft32, h8300, hppa, hppa2.0, hppa64, i486, i686, ia64, iq2000, lm32, loongarch64, m32c, m32r, m32rle, m68k, mcore, microblaze, microblazeel, mips, mips64, mips64el, mips64octeon, mips64orion, mips64vr, mipsel, mipsisa32, mipsisa32r2, mipsisa64, mipsisa64r2, @@ -3825,29 +3825,6 @@ are available at @uref{https://sourceforge.net/projects/adi-toolchain/}. @html <hr /> @end html -@anchor{cr16} -@heading CR16 -The CR16 CompactRISC architecture is a 16-bit architecture. This -architecture is used in embedded applications. - -@ifnothtml -@xref{CR16 Options,, CR16 Options, gcc, Using and Porting the GNU Compiler -Collection (GCC)}, -@end ifnothtml - -@ifhtml -See ``CR16 Options'' in the main manual for a list of CR16-specific options. -@end ifhtml - -Use @samp{configure --target=cr16-elf --enable-languages=c,c++} to configure -GCC@ for building a CR16 elf cross-compiler. - -Use @samp{configure --target=cr16-uclinux --enable-languages=c,c++} to -configure GCC@ for building a CR16 uclinux cross-compiler. - -@html -<hr /> -@end html @anchor{cris} @heading CRIS CRIS is a CPU architecture in Axis Communications systems-on-a-chip, for @@ -3898,8 +3875,7 @@ on FreeBSD 7 or later) and the use of @code{__cxa_atexit} by default by GCC 4.5 and above. We support FreeBSD using the ELF file format with DWARF 2 debugging -for all CPU architectures. You may use @option{-gstabs} instead of -@option{-g}, if you really want the old debugging format. There are +for all CPU architectures. There are no known issues with mixing object files and libraries with different debugging formats. Otherwise, this release of GCC should now match more of the configuration used in the stock FreeBSD configuration of diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0cec884..9124794 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -16,7 +16,6 @@ gcc [@option{-c}|@option{-S}|@option{-E}] [@option{-std=}@var{standard}] Only the most useful options are listed here; see below for the remainder. @command{g++} accepts mostly the same options as @command{gcc}. - For instructions on reporting bugs, see $$BUGURL$$. @@ -227,7 +226,7 @@ in the following sections. -Wreorder -Wregister @gol -Wstrict-null-sentinel -Wno-subobject-linkage -Wtemplates @gol -Wno-non-template-friend -Wold-style-cast @gol --Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo @gol +-Woverloaded-virtual -Wno-pmf-conversions -Wself-move -Wsign-promo @gol -Wsized-deallocation -Wsuggest-final-methods @gol -Wsuggest-final-types -Wsuggest-override @gol -Wno-terminate -Wuseless-cast -Wno-vexing-parse @gol @@ -328,9 +327,9 @@ Objective-C and Objective-C++ Dialects}. -Winfinite-recursion @gol -Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context @gol -Wno-int-to-pointer-cast -Wno-invalid-memory-model @gol --Winvalid-pch -Wjump-misses-init -Wlarger-than=@var{byte-size} @gol --Wlogical-not-parentheses -Wlogical-op -Wlong-long @gol --Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized @gol +-Winvalid-pch -Winvalid-utf8 -Wjump-misses-init @gol +-Wlarger-than=@var{byte-size} -Wlogical-not-parentheses -Wlogical-op @gol +-Wlong-long -Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized @gol -Wmemset-elt-size -Wmemset-transposed-args @gol -Wmisleading-indentation -Wmissing-attributes -Wmissing-braces @gol -Wmissing-field-initializers -Wmissing-format-attribute @gol @@ -377,6 +376,7 @@ Objective-C and Objective-C++ Dialects}. -Wvector-operation-performance @gol -Wvla -Wvla-larger-than=@var{byte-size} -Wno-vla-larger-than @gol -Wvolatile-register-var -Wwrite-strings @gol +-Wxor-used-as-pow @gol -Wzero-length-bounds} @item Static Analyzer Options @@ -459,7 +459,7 @@ Objective-C and Objective-C++ Dialects}. @gccoptlist{-g -g@var{level} -gdwarf -gdwarf-@var{version} @gol -gbtf -gctf -gctf@var{level} @gol -ggdb -grecord-gcc-switches -gno-record-gcc-switches @gol --gstabs -gstabs+ -gstrict-dwarf -gno-strict-dwarf @gol +-gstrict-dwarf -gno-strict-dwarf @gol -gas-loc-support -gno-as-loc-support @gol -gas-locview-support -gno-as-locview-support @gol -gcolumn-info -gno-column-info -gdwarf32 -gdwarf64 @gol @@ -467,7 +467,7 @@ Objective-C and Objective-C++ Dialects}. -gvariable-location-views -gno-variable-location-views @gol -ginternal-reset-location-views -gno-internal-reset-location-views @gol -ginline-points -gno-inline-points @gol --gvms -gxcoff -gxcoff+ -gz@r{[}=@var{type}@r{]} @gol +-gvms -gz@r{[}=@var{type}@r{]} @gol -gsplit-dwarf -gdescribe-dies -gno-describe-dies @gol -fdebug-prefix-map=@var{old}=@var{new} -fdebug-types-section @gol -fno-eliminate-unused-debug-types @gol @@ -842,12 +842,6 @@ Objective-C and Objective-C++ Dialects}. -melf -maout -sim -sim2 @gol -mmul-bug-workaround -mno-mul-bug-workaround} -@emph{CR16 Options} -@gccoptlist{-mmac @gol --mcr16cplus -mcr16c @gol --msim -mint32 -mbit-ops --mdata-model=@var{model}} - @emph{C-SKY Options} @gccoptlist{-march=@var{arch} -mcpu=@var{cpu} @gol -mbig-endian -EB -mlittle-endian -EL @gol @@ -5807,6 +5801,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. -Wreorder @gol -Wrestrict @gol -Wreturn-type @gol +-Wself-move @r{(only for C++)} @gol -Wsequence-point @gol -Wsign-compare @r{(only in C++)} @gol -Wsizeof-array-div @gol @@ -6792,6 +6787,26 @@ of a declaration: This warning is enabled by @option{-Wall}. +@item -Wno-self-move @r{(C++ and Objective-C++ only)} +@opindex Wself-move +@opindex Wno-self-move +This warning warns when a value is moved to itself with @code{std::move}. +Such a @code{std::move} typically has no effect. + +@smallexample +struct T @{ +@dots{} +@}; +void fn() +@{ + T t; + @dots{} + t = std::move (t); +@} +@end smallexample + +This warning is enabled by @option{-Wall}. + @item -Wsequence-point @opindex Wsequence-point @opindex Wno-sequence-point @@ -9517,6 +9532,13 @@ different size. Warn if a precompiled header (@pxref{Precompiled Headers}) is found in the search path but cannot be used. +@item -Winvalid-utf8 +@opindex Winvalid-utf8 +@opindex Wno-invalid-utf8 +Warn if an invalid UTF-8 character is found. +This warning is on by default for C++23 if @option{-finput-charset=UTF-8} +is used and turned into error with @option{-pedantic-errors}. + @item -Wlong-long @opindex Wlong-long @opindex Wno-long-long @@ -9627,6 +9649,20 @@ modifier does not inhibit all optimizations that may eliminate reads and/or writes to register variables. This warning is enabled by @option{-Wall}. +@item -Wxor-used-as-pow @r{(C, C++, Objective-C and Objective-C++ only)} +@opindex Wxor-used-as-pow +@opindex Wno-xor-used-as-pow +Warn about uses of @code{^}, the exclusive or operator, where it appears +the user meant exponentiation. Specifically, the warning occurs when the +left-hand side is the decimal constant 2 or 10 and the right-hand side +is also a decimal constant. + +In C and C++, @code{^} means exclusive or, whereas in some other languages +(e.g. TeX and some versions of BASIC) it means exponentiation. + +This warning is enabled by default. It can be silenced by converting one +of the operands to hexadecimal. + @item -Wdisabled-optimization @opindex Wdisabled-optimization @opindex Wno-disabled-optimization @@ -10648,10 +10684,8 @@ information. On most systems that use stabs format, @option{-g} enables use of extra debugging information that only GDB can use; this extra information makes debugging work better in GDB but probably makes other debuggers -crash or -refuse to read the program. If you want to control for certain whether -to generate the extra information, use @option{-gstabs+}, @option{-gstabs}, -@option{-gxcoff+}, @option{-gxcoff}, or @option{-gvms} (see below). +crash or refuse to read the program. If you want to control for certain whether +to generate the extra information, use @option{-gvms} (see below). @item -ggdb @opindex ggdb @@ -10708,34 +10742,6 @@ information, but does not include type information. Level 2 produces type information for entities (functions, data objects etc.) at file-scope or global-scope only. -@item -gstabs -@opindex gstabs -Produce debugging information in stabs format (if that is supported), -without GDB extensions. This is the format used by DBX on most BSD -systems. On MIPS, Alpha and System V Release 4 systems this option -produces stabs debugging output that is not understood by DBX@. -On System V Release 4 systems this option requires the GNU assembler. - -@item -gstabs+ -@opindex gstabs+ -Produce debugging information in stabs format (if that is supported), -using GNU extensions understood only by the GNU debugger (GDB)@. The -use of these extensions is likely to make other debuggers crash or -refuse to read the program. - -@item -gxcoff -@opindex gxcoff -Produce debugging information in XCOFF format (if that is supported). -This is the format used by the DBX debugger on IBM RS/6000 systems. - -@item -gxcoff+ -@opindex gxcoff+ -Produce debugging information in XCOFF format (if that is supported), -using GNU extensions understood only by the GNU debugger (GDB)@. The -use of these extensions is likely to make other debuggers crash or -refuse to read the program, and may cause assemblers other than the GNU -assembler (GAS) to fail with an error. - @item -gvms @opindex gvms Produce debugging information in Alpha/VMS debug format (if that is @@ -10743,8 +10749,6 @@ supported). This is the format used by DEBUG on Alpha/VMS systems. @item -g@var{level} @itemx -ggdb@var{level} -@itemx -gstabs@var{level} -@itemx -gxcoff@var{level} @itemx -gvms@var{level} Request debugging information and also use @var{level} to specify how much information. The default level is 2. @@ -11819,7 +11823,7 @@ Use @option{-fno-delete-null-pointer-checks} to disable this optimization for programs that depend on that behavior. This option is enabled by default on most targets. On Nios II ELF, it -defaults to off. On AVR, CR16, and MSP430, this option is completely disabled. +defaults to off. On AVR and MSP430, this option is completely disabled. Passes that use the dataflow information are enabled independently at different optimization levels. @@ -14567,6 +14571,10 @@ Complex expressions slow the analyzer. Maximum number of arguments in a PHI supported by TREE if conversion unless the loop is marked with simd pragma. +@item vect-max-layout-candidates +The maximum number of possible vector layouts (such as permutations) +to consider when optimizing to-be-vectorized code. + @item vect-max-version-for-alignment-checks The maximum number of run-time checks that can be performed when doing loop versioning for alignment in the vectorizer. @@ -19366,7 +19374,6 @@ platform. * Blackfin Options:: * C6X Options:: * CRIS Options:: -* CR16 Options:: * C-SKY Options:: * Darwin Options:: * DEC Alpha Options:: @@ -22943,46 +22950,6 @@ Like @option{-sim}, but pass linker options to locate initialized data at 0x40000000 and zero-initialized data at 0x80000000. @end table -@node CR16 Options -@subsection CR16 Options -@cindex CR16 Options - -These options are defined specifically for the CR16 ports. - -@table @gcctabopt - -@item -mmac -@opindex mmac -Enable the use of multiply-accumulate instructions. Disabled by default. - -@item -mcr16cplus -@itemx -mcr16c -@opindex mcr16cplus -@opindex mcr16c -Generate code for CR16C or CR16C+ architecture. CR16C+ architecture -is default. - -@item -msim -@opindex msim -Links the library libsim.a which is in compatible with simulator. Applicable -to ELF compiler only. - -@item -mint32 -@opindex mint32 -Choose integer type as 32-bit wide. - -@item -mbit-ops -@opindex mbit-ops -Generates @code{sbit}/@code{cbit} instructions for bit manipulations. - -@item -mdata-model=@var{model} -@opindex mdata-model -Choose a data model. The choices for @var{model} are @samp{near}, -@samp{far} or @samp{medium}. @samp{medium} is default. -However, @samp{far} is not valid with @option{-mcr16c}, as the -CR16C architecture does not support the far data model. -@end table - @node C-SKY Options @subsection C-SKY Options @cindex C-SKY Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 04aedfa..3482554 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2198,40 +2198,6 @@ An integer constant with all bits set except exactly one. Any SYMBOL_REF. @end table -@item CR16 Architecture---@file{config/cr16/cr16.h} -@table @code - -@item b -Registers from r0 to r14 (registers without stack pointer) - -@item t -Register from r0 to r11 (all 16-bit registers) - -@item p -Register from r12 to r15 (all 32-bit registers) - -@item I -Signed constant that fits in 4 bits - -@item J -Signed constant that fits in 5 bits - -@item K -Signed constant that fits in 6 bits - -@item L -Unsigned constant that fits in 4 bits - -@item M -Signed constant that fits in 32 bits - -@item N -Check for 64 bits wide constants for add/sub instructions - -@item G -Floating point constant that is legal for store immediate -@end table - @item C-SKY---@file{config/csky/constraints.md} @table @code @@ -6184,6 +6150,10 @@ floating-point mode. This pattern is not allowed to @code{FAIL}. +@cindex @code{issignaling@var{m}2} instruction pattern +@item @samp{issignaling@var{m}2} +Set operand 0 to 1 if operand 1 is a signaling NaN and to 0 otherwise. + @cindex @code{cadd90@var{m}3} instruction pattern @item @samp{cadd90@var{m}3} Perform vector add and subtract on even/odd number pairs. The operation being diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi index 1e821d4..9e8b4f5 100644 --- a/gcc/doc/passes.texi +++ b/gcc/doc/passes.texi @@ -1184,7 +1184,7 @@ these files. This is run after final because it must output the stack slot offsets for pseudo registers that did not get hard registers. Source files -are @file{dbxout.cc} for DBX symbol table format, @file{dwarfout.c} for +are @file{dwarfout.c} for DWARF symbol table format, files @file{dwarf2out.cc} and @file{dwarf2asm.cc} for DWARF2 symbol table format, and @file{vmsdbgout.cc} for VMS debug symbol table format. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index af403e8..09476f8 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -801,6 +801,23 @@ Set target-dependent initial values of fields in @var{opts}. @end deftypefn @c hook-end +@deftypefn {Common Target Hook} {const char *} TARGET_COMPUTE_MULTILIB (const struct switchstr *@var{switches}, int @var{n_switches}, const char *@var{multilib_dir}, const char *@var{multilib_defaults}, const char *@var{multilib_select}, const char *@var{multilib_matches}, const char *@var{multilib_exclusions}, const char *@var{multilib_reuse}) +Some targets like RISC-V might have complicated multilib reuse rules which +are hard to implement with the current multilib scheme. This hook allows +targets to override the result from the built-in multilib mechanism. +@var{switches} is the raw option list with @var{n_switches} items; +@var{multilib_dir} is the multi-lib result which is computed by the built-in +multi-lib mechanism; +@var{multilib_defaults} is the default options list for multi-lib; +@var{multilib_select} is the string containing the list of supported +multi-libs, and the option checking list. +@var{multilib_matches}, @var{multilib_exclusions}, and @var{multilib_reuse} +are corresponding to @var{MULTILIB_MATCHES}, @var{MULTILIB_EXCLUSIONS}, +and @var{MULTILIB_REUSE}. +The default definition does nothing but return @var{multilib_dir} directly. +@end deftypefn + + @defmac SWITCHABLE_TARGET Some targets need to switch between substantially different subtargets during compilation. For example, the MIPS target has one subtarget for @@ -3905,7 +3922,7 @@ Define this macro if the target's representation for dwarf registers used in .eh_frame or .debug_frame is different from that used in other debug info sections. Given a GCC hard register number, this macro should return the .eh_frame register number. The default is -@code{DBX_REGISTER_NUMBER (@var{regno})}. +@code{DEBUGGER_REGISTER_NUMBER (@var{regno})}. @end defmac @@ -6621,6 +6638,9 @@ stores. This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float} fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also @var{simdlen} field if it was previously 0. +@var{vecsize_mangle} is a marker for the backend only. @var{vecsize_int} and +@var{vecsize_float} should be left zero on targets where the number of lanes is +not determined by the bitsize (in which case @var{simdlen} is always used). The hook should return 0 if SIMD clones shouldn't be emitted, or number of @var{vecsize_mangle} variants that should be emitted. @end deftypefn @@ -10571,9 +10591,6 @@ This describes how to specify debugging information. @menu * All Debuggers:: Macros that affect all debugging formats uniformly. -* DBX Options:: Macros enabling specific options in DBX format. -* DBX Hooks:: Hook macros for varying DBX format. -* File Names and DBX:: Macros controlling output of file names in DBX format. * DWARF:: Macros for DWARF format. * VMS Debug:: Macros for VMS debug format. * CTF Debug:: Macros for CTF debug format. @@ -10586,21 +10603,21 @@ This describes how to specify debugging information. @c prevent bad page break with this line These macros affect all debugging formats. -@defmac DBX_REGISTER_NUMBER (@var{regno}) -A C expression that returns the DBX register number for the compiler +@defmac DEBUGGER_REGISTER_NUMBER (@var{regno}) +A C expression that returns the debugger register number for the compiler register number @var{regno}. In the default macro provided, the value of this expression will be @var{regno} itself. But sometimes there are -some registers that the compiler knows about and DBX does not, or vice +some registers that the compiler knows about and debugger does not, or vice versa. In such cases, some register may need to have one number in the -compiler and another for DBX@. +compiler and another for debugger@. If two registers have consecutive numbers inside GCC, and they can be used as a pair to hold a multiword value, then they @emph{must} have -consecutive numbers after renumbering with @code{DBX_REGISTER_NUMBER}. +consecutive numbers after renumbering with @code{DEBUGGER_REGISTER_NUMBER}. Otherwise, debuggers will be unable to access such a pair, because they expect register pairs to be consecutive in their own numbering scheme. -If you find yourself defining @code{DBX_REGISTER_NUMBER} in way that +If you find yourself defining @code{DEBUGGER_REGISTER_NUMBER} in way that does not preserve register pairs, then what you must do instead is redefine the actual register numbering scheme. @end defmac @@ -10610,7 +10627,7 @@ A C expression that returns the integer offset value for an automatic variable having address @var{x} (an RTL expression). The default computation assumes that @var{x} is based on the frame-pointer and gives the offset from the frame-pointer. This is required for targets -that produce debugging output for DBX and allow the frame-pointer to be +that produce debugging output for debugger and allow the frame-pointer to be eliminated when the @option{-g} option is used. @end defmac @@ -10624,235 +10641,27 @@ having address @var{x} (an RTL expression). The nominal offset is A C expression that returns the type of debugging output GCC should produce when the user specifies just @option{-g}. Define this if you have arranged for GCC to support more than one format of -debugging output. Currently, the allowable values are @code{DBX_DEBUG}, -@code{DWARF2_DEBUG}, @code{XCOFF_DEBUG}, @code{VMS_DEBUG}, +debugging output. Currently, the allowable values are +@code{DWARF2_DEBUG}, @code{VMS_DEBUG}, and @code{VMS_AND_DWARF2_DEBUG}. When the user specifies @option{-ggdb}, GCC normally also uses the value of this macro to select the debugging output format, but with two exceptions. If @code{DWARF2_DEBUGGING_INFO} is defined, GCC uses the -value @code{DWARF2_DEBUG}. Otherwise, if @code{DBX_DEBUGGING_INFO} is -defined, GCC uses @code{DBX_DEBUG}. +value @code{DWARF2_DEBUG}. The value of this macro only affects the default debugging output; the -user can always get a specific type of output by using @option{-gstabs}, -@option{-gdwarf-2}, @option{-gxcoff}, or @option{-gvms}. -@end defmac - -@node DBX Options -@subsection Specific Options for DBX Output - -@c prevent bad page break with this line -These are specific options for DBX output. - -@defmac DBX_DEBUGGING_INFO -Define this macro if GCC should produce debugging output for DBX -in response to the @option{-g} option. -@end defmac - -@defmac XCOFF_DEBUGGING_INFO -Define this macro if GCC should produce XCOFF format debugging output -in response to the @option{-g} option. This is a variant of DBX format. +user can always get a specific type of output by using @option{-gdwarf-2}, +or @option{-gvms}. @end defmac @defmac DEFAULT_GDB_EXTENSIONS Define this macro to control whether GCC should by default generate -GDB's extended version of DBX debugging information (assuming DBX-format -debugging information is enabled at all). If you don't define the +GDB's extended version of debugging information. If you don't define the macro, the default is 1: always generate the extended information if there is any occasion to. @end defmac -@defmac DEBUG_SYMS_TEXT -Define this macro if all @code{.stabs} commands should be output while -in the text section. -@end defmac - -@defmac ASM_STABS_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabs\t"} to define an ordinary debugging symbol. -If you don't define this macro, @code{"\t.stabs\t"} is used. This macro -applies only to DBX debugging information format. -@end defmac - -@defmac ASM_STABD_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabd\t"} to define a debugging symbol whose -value is the current location. If you don't define this macro, -@code{"\t.stabd\t"} is used. This macro applies only to DBX debugging -information format. -@end defmac - -@defmac ASM_STABN_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabn\t"} to define a debugging symbol with no -name. If you don't define this macro, @code{"\t.stabn\t"} is used. This -macro applies only to DBX debugging information format. -@end defmac - -@defmac DBX_NO_XREFS -Define this macro if DBX on your system does not support the construct -@samp{xs@var{tagname}}. On some systems, this construct is used to -describe a forward reference to a structure named @var{tagname}. -On other systems, this construct is not supported at all. -@end defmac - -@defmac DBX_CONTIN_LENGTH -A symbol name in DBX-format debugging information is normally -continued (split into two separate @code{.stabs} directives) when it -exceeds a certain length (by default, 80 characters). On some -operating systems, DBX requires this splitting; on others, splitting -must not be done. You can inhibit splitting by defining this macro -with the value zero. You can override the default splitting-length by -defining this macro as an expression for the length you desire. -@end defmac - -@defmac DBX_CONTIN_CHAR -Normally continuation is indicated by adding a @samp{\} character to -the end of a @code{.stabs} string when a continuation follows. To use -a different character instead, define this macro as a character -constant for the character you want to use. Do not define this macro -if backslash is correct for your system. -@end defmac - -@defmac DBX_STATIC_STAB_DATA_SECTION -Define this macro if it is necessary to go to the data section before -outputting the @samp{.stabs} pseudo-op for a non-global static -variable. -@end defmac - -@defmac DBX_TYPE_DECL_STABS_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a typedef. The default is @code{N_LSYM}. -@end defmac - -@defmac DBX_STATIC_CONST_VAR_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a static variable located in the text section. DBX format does not -provide any ``right'' way to do this. The default is @code{N_FUN}. -@end defmac - -@defmac DBX_REGPARM_STABS_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a parameter passed in registers. DBX format does not provide any -``right'' way to do this. The default is @code{N_RSYM}. -@end defmac - -@defmac DBX_REGPARM_STABS_LETTER -The letter to use in DBX symbol data to identify a symbol as a parameter -passed in registers. DBX format does not customarily provide any way to -do this. The default is @code{'P'}. -@end defmac - -@defmac DBX_FUNCTION_FIRST -Define this macro if the DBX information for a function and its -arguments should precede the assembler code for the function. Normally, -in DBX format, the debugging information entirely follows the assembler -code. -@end defmac - -@defmac DBX_BLOCKS_FUNCTION_RELATIVE -Define this macro, with value 1, if the value of a symbol describing -the scope of a block (@code{N_LBRAC} or @code{N_RBRAC}) should be -relative to the start of the enclosing function. Normally, GCC uses -an absolute address. -@end defmac - -@defmac DBX_LINES_FUNCTION_RELATIVE -Define this macro, with value 1, if the value of a symbol indicating -the current line number (@code{N_SLINE}) should be relative to the -start of the enclosing function. Normally, GCC uses an absolute address. -@end defmac - -@defmac DBX_USE_BINCL -Define this macro if GCC should generate @code{N_BINCL} and -@code{N_EINCL} stabs for included header files, as on Sun systems. This -macro also directs GCC to output a type number as a pair of a file -number and a type number within the file. Normally, GCC does not -generate @code{N_BINCL} or @code{N_EINCL} stabs, and it outputs a single -number for a type number. -@end defmac - -@node DBX Hooks -@subsection Open-Ended Hooks for DBX Format - -@c prevent bad page break with this line -These are hooks for DBX format. - -@defmac DBX_OUTPUT_SOURCE_LINE (@var{stream}, @var{line}, @var{counter}) -A C statement to output DBX debugging information before code for line -number @var{line} of the current source file to the stdio stream -@var{stream}. @var{counter} is the number of time the macro was -invoked, including the current invocation; it is intended to generate -unique labels in the assembly output. - -This macro should not be defined if the default output is correct, or -if it can be made correct by defining @code{DBX_LINES_FUNCTION_RELATIVE}. -@end defmac - -@defmac NO_DBX_FUNCTION_END -Some stabs encapsulation formats (in particular ECOFF), cannot handle the -@code{.stabs "",N_FUN,,0,0,Lscope-function-1} gdb dbx extension construct. -On those machines, define this macro to turn this feature off without -disturbing the rest of the gdb extensions. -@end defmac - -@defmac NO_DBX_BNSYM_ENSYM -Some assemblers cannot handle the @code{.stabd BNSYM/ENSYM,0,0} gdb dbx -extension construct. On those machines, define this macro to turn this -feature off without disturbing the rest of the gdb extensions. -@end defmac - -@node File Names and DBX -@subsection File Names in DBX Format - -@c prevent bad page break with this line -This describes file names in DBX format. - -@defmac DBX_OUTPUT_MAIN_SOURCE_FILENAME (@var{stream}, @var{name}) -A C statement to output DBX debugging information to the stdio stream -@var{stream}, which indicates that file @var{name} is the main source -file---the file specified as the input file for compilation. -This macro is called only once, at the beginning of compilation. - -This macro need not be defined if the standard form of output -for DBX debugging information is appropriate. - -It may be necessary to refer to a label equal to the beginning of the -text section. You can use @samp{assemble_name (stream, ltext_label_name)} -to do so. If you do this, you must also set the variable -@var{used_ltext_label_name} to @code{true}. -@end defmac - -@defmac NO_DBX_MAIN_SOURCE_DIRECTORY -Define this macro, with value 1, if GCC should not emit an indication -of the current directory for compilation and current source language at -the beginning of the file. -@end defmac - -@defmac NO_DBX_GCC_MARKER -Define this macro, with value 1, if GCC should not emit an indication -that this object file was compiled by GCC@. The default is to emit -an @code{N_OPT} stab at the beginning of every source file, with -@samp{gcc2_compiled.} for the string and value 0. -@end defmac - -@defmac DBX_OUTPUT_MAIN_SOURCE_FILE_END (@var{stream}, @var{name}) -A C statement to output DBX debugging information at the end of -compilation of the main source file @var{name}. Output should be -written to the stdio stream @var{stream}. - -If you don't define this macro, nothing special is output at the end -of compilation, which is correct for most machines. -@end defmac - -@defmac DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END -Define this macro @emph{instead of} defining -@code{DBX_OUTPUT_MAIN_SOURCE_FILE_END}, if what needs to be output at -the end of compilation is an @code{N_SO} stab with an empty string, -whose value is the highest absolute text address in the file. -@end defmac - @need 2000 @node DWARF @subsection Macros for DWARF Output diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 1124623..955343a 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -736,6 +736,9 @@ options are changed via @code{#pragma GCC optimize} or by using the @hook TARGET_OPTION_INIT_STRUCT +@hook TARGET_COMPUTE_MULTILIB + + @defmac SWITCHABLE_TARGET Some targets need to switch between substantially different subtargets during compilation. For example, the MIPS target has one subtarget for @@ -3009,7 +3012,7 @@ Define this macro if the target's representation for dwarf registers used in .eh_frame or .debug_frame is different from that used in other debug info sections. Given a GCC hard register number, this macro should return the .eh_frame register number. The default is -@code{DBX_REGISTER_NUMBER (@var{regno})}. +@code{DEBUGGER_REGISTER_NUMBER (@var{regno})}. @end defmac @@ -6603,9 +6606,6 @@ This describes how to specify debugging information. @menu * All Debuggers:: Macros that affect all debugging formats uniformly. -* DBX Options:: Macros enabling specific options in DBX format. -* DBX Hooks:: Hook macros for varying DBX format. -* File Names and DBX:: Macros controlling output of file names in DBX format. * DWARF:: Macros for DWARF format. * VMS Debug:: Macros for VMS debug format. * CTF Debug:: Macros for CTF debug format. @@ -6618,21 +6618,21 @@ This describes how to specify debugging information. @c prevent bad page break with this line These macros affect all debugging formats. -@defmac DBX_REGISTER_NUMBER (@var{regno}) -A C expression that returns the DBX register number for the compiler +@defmac DEBUGGER_REGISTER_NUMBER (@var{regno}) +A C expression that returns the debugger register number for the compiler register number @var{regno}. In the default macro provided, the value of this expression will be @var{regno} itself. But sometimes there are -some registers that the compiler knows about and DBX does not, or vice +some registers that the compiler knows about and debugger does not, or vice versa. In such cases, some register may need to have one number in the -compiler and another for DBX@. +compiler and another for debugger@. If two registers have consecutive numbers inside GCC, and they can be used as a pair to hold a multiword value, then they @emph{must} have -consecutive numbers after renumbering with @code{DBX_REGISTER_NUMBER}. +consecutive numbers after renumbering with @code{DEBUGGER_REGISTER_NUMBER}. Otherwise, debuggers will be unable to access such a pair, because they expect register pairs to be consecutive in their own numbering scheme. -If you find yourself defining @code{DBX_REGISTER_NUMBER} in way that +If you find yourself defining @code{DEBUGGER_REGISTER_NUMBER} in way that does not preserve register pairs, then what you must do instead is redefine the actual register numbering scheme. @end defmac @@ -6642,7 +6642,7 @@ A C expression that returns the integer offset value for an automatic variable having address @var{x} (an RTL expression). The default computation assumes that @var{x} is based on the frame-pointer and gives the offset from the frame-pointer. This is required for targets -that produce debugging output for DBX and allow the frame-pointer to be +that produce debugging output for debugger and allow the frame-pointer to be eliminated when the @option{-g} option is used. @end defmac @@ -6656,235 +6656,27 @@ having address @var{x} (an RTL expression). The nominal offset is A C expression that returns the type of debugging output GCC should produce when the user specifies just @option{-g}. Define this if you have arranged for GCC to support more than one format of -debugging output. Currently, the allowable values are @code{DBX_DEBUG}, -@code{DWARF2_DEBUG}, @code{XCOFF_DEBUG}, @code{VMS_DEBUG}, +debugging output. Currently, the allowable values are +@code{DWARF2_DEBUG}, @code{VMS_DEBUG}, and @code{VMS_AND_DWARF2_DEBUG}. When the user specifies @option{-ggdb}, GCC normally also uses the value of this macro to select the debugging output format, but with two exceptions. If @code{DWARF2_DEBUGGING_INFO} is defined, GCC uses the -value @code{DWARF2_DEBUG}. Otherwise, if @code{DBX_DEBUGGING_INFO} is -defined, GCC uses @code{DBX_DEBUG}. +value @code{DWARF2_DEBUG}. The value of this macro only affects the default debugging output; the -user can always get a specific type of output by using @option{-gstabs}, -@option{-gdwarf-2}, @option{-gxcoff}, or @option{-gvms}. -@end defmac - -@node DBX Options -@subsection Specific Options for DBX Output - -@c prevent bad page break with this line -These are specific options for DBX output. - -@defmac DBX_DEBUGGING_INFO -Define this macro if GCC should produce debugging output for DBX -in response to the @option{-g} option. -@end defmac - -@defmac XCOFF_DEBUGGING_INFO -Define this macro if GCC should produce XCOFF format debugging output -in response to the @option{-g} option. This is a variant of DBX format. +user can always get a specific type of output by using @option{-gdwarf-2}, +or @option{-gvms}. @end defmac @defmac DEFAULT_GDB_EXTENSIONS Define this macro to control whether GCC should by default generate -GDB's extended version of DBX debugging information (assuming DBX-format -debugging information is enabled at all). If you don't define the +GDB's extended version of debugging information. If you don't define the macro, the default is 1: always generate the extended information if there is any occasion to. @end defmac -@defmac DEBUG_SYMS_TEXT -Define this macro if all @code{.stabs} commands should be output while -in the text section. -@end defmac - -@defmac ASM_STABS_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabs\t"} to define an ordinary debugging symbol. -If you don't define this macro, @code{"\t.stabs\t"} is used. This macro -applies only to DBX debugging information format. -@end defmac - -@defmac ASM_STABD_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabd\t"} to define a debugging symbol whose -value is the current location. If you don't define this macro, -@code{"\t.stabd\t"} is used. This macro applies only to DBX debugging -information format. -@end defmac - -@defmac ASM_STABN_OP -A C string constant, including spacing, naming the assembler pseudo op to -use instead of @code{"\t.stabn\t"} to define a debugging symbol with no -name. If you don't define this macro, @code{"\t.stabn\t"} is used. This -macro applies only to DBX debugging information format. -@end defmac - -@defmac DBX_NO_XREFS -Define this macro if DBX on your system does not support the construct -@samp{xs@var{tagname}}. On some systems, this construct is used to -describe a forward reference to a structure named @var{tagname}. -On other systems, this construct is not supported at all. -@end defmac - -@defmac DBX_CONTIN_LENGTH -A symbol name in DBX-format debugging information is normally -continued (split into two separate @code{.stabs} directives) when it -exceeds a certain length (by default, 80 characters). On some -operating systems, DBX requires this splitting; on others, splitting -must not be done. You can inhibit splitting by defining this macro -with the value zero. You can override the default splitting-length by -defining this macro as an expression for the length you desire. -@end defmac - -@defmac DBX_CONTIN_CHAR -Normally continuation is indicated by adding a @samp{\} character to -the end of a @code{.stabs} string when a continuation follows. To use -a different character instead, define this macro as a character -constant for the character you want to use. Do not define this macro -if backslash is correct for your system. -@end defmac - -@defmac DBX_STATIC_STAB_DATA_SECTION -Define this macro if it is necessary to go to the data section before -outputting the @samp{.stabs} pseudo-op for a non-global static -variable. -@end defmac - -@defmac DBX_TYPE_DECL_STABS_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a typedef. The default is @code{N_LSYM}. -@end defmac - -@defmac DBX_STATIC_CONST_VAR_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a static variable located in the text section. DBX format does not -provide any ``right'' way to do this. The default is @code{N_FUN}. -@end defmac - -@defmac DBX_REGPARM_STABS_CODE -The value to use in the ``code'' field of the @code{.stabs} directive -for a parameter passed in registers. DBX format does not provide any -``right'' way to do this. The default is @code{N_RSYM}. -@end defmac - -@defmac DBX_REGPARM_STABS_LETTER -The letter to use in DBX symbol data to identify a symbol as a parameter -passed in registers. DBX format does not customarily provide any way to -do this. The default is @code{'P'}. -@end defmac - -@defmac DBX_FUNCTION_FIRST -Define this macro if the DBX information for a function and its -arguments should precede the assembler code for the function. Normally, -in DBX format, the debugging information entirely follows the assembler -code. -@end defmac - -@defmac DBX_BLOCKS_FUNCTION_RELATIVE -Define this macro, with value 1, if the value of a symbol describing -the scope of a block (@code{N_LBRAC} or @code{N_RBRAC}) should be -relative to the start of the enclosing function. Normally, GCC uses -an absolute address. -@end defmac - -@defmac DBX_LINES_FUNCTION_RELATIVE -Define this macro, with value 1, if the value of a symbol indicating -the current line number (@code{N_SLINE}) should be relative to the -start of the enclosing function. Normally, GCC uses an absolute address. -@end defmac - -@defmac DBX_USE_BINCL -Define this macro if GCC should generate @code{N_BINCL} and -@code{N_EINCL} stabs for included header files, as on Sun systems. This -macro also directs GCC to output a type number as a pair of a file -number and a type number within the file. Normally, GCC does not -generate @code{N_BINCL} or @code{N_EINCL} stabs, and it outputs a single -number for a type number. -@end defmac - -@node DBX Hooks -@subsection Open-Ended Hooks for DBX Format - -@c prevent bad page break with this line -These are hooks for DBX format. - -@defmac DBX_OUTPUT_SOURCE_LINE (@var{stream}, @var{line}, @var{counter}) -A C statement to output DBX debugging information before code for line -number @var{line} of the current source file to the stdio stream -@var{stream}. @var{counter} is the number of time the macro was -invoked, including the current invocation; it is intended to generate -unique labels in the assembly output. - -This macro should not be defined if the default output is correct, or -if it can be made correct by defining @code{DBX_LINES_FUNCTION_RELATIVE}. -@end defmac - -@defmac NO_DBX_FUNCTION_END -Some stabs encapsulation formats (in particular ECOFF), cannot handle the -@code{.stabs "",N_FUN,,0,0,Lscope-function-1} gdb dbx extension construct. -On those machines, define this macro to turn this feature off without -disturbing the rest of the gdb extensions. -@end defmac - -@defmac NO_DBX_BNSYM_ENSYM -Some assemblers cannot handle the @code{.stabd BNSYM/ENSYM,0,0} gdb dbx -extension construct. On those machines, define this macro to turn this -feature off without disturbing the rest of the gdb extensions. -@end defmac - -@node File Names and DBX -@subsection File Names in DBX Format - -@c prevent bad page break with this line -This describes file names in DBX format. - -@defmac DBX_OUTPUT_MAIN_SOURCE_FILENAME (@var{stream}, @var{name}) -A C statement to output DBX debugging information to the stdio stream -@var{stream}, which indicates that file @var{name} is the main source -file---the file specified as the input file for compilation. -This macro is called only once, at the beginning of compilation. - -This macro need not be defined if the standard form of output -for DBX debugging information is appropriate. - -It may be necessary to refer to a label equal to the beginning of the -text section. You can use @samp{assemble_name (stream, ltext_label_name)} -to do so. If you do this, you must also set the variable -@var{used_ltext_label_name} to @code{true}. -@end defmac - -@defmac NO_DBX_MAIN_SOURCE_DIRECTORY -Define this macro, with value 1, if GCC should not emit an indication -of the current directory for compilation and current source language at -the beginning of the file. -@end defmac - -@defmac NO_DBX_GCC_MARKER -Define this macro, with value 1, if GCC should not emit an indication -that this object file was compiled by GCC@. The default is to emit -an @code{N_OPT} stab at the beginning of every source file, with -@samp{gcc2_compiled.} for the string and value 0. -@end defmac - -@defmac DBX_OUTPUT_MAIN_SOURCE_FILE_END (@var{stream}, @var{name}) -A C statement to output DBX debugging information at the end of -compilation of the main source file @var{name}. Output should be -written to the stdio stream @var{stream}. - -If you don't define this macro, nothing special is output at the end -of compilation, which is correct for most machines. -@end defmac - -@defmac DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END -Define this macro @emph{instead of} defining -@code{DBX_OUTPUT_MAIN_SOURCE_FILE_END}, if what needs to be output at -the end of compilation is an @code{N_SO} stab with an empty string, -whose value is the highest absolute text address in the file. -@end defmac - @need 2000 @node DWARF @subsection Macros for DWARF Output diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h index 3c47f09..b2219c5 100644 --- a/gcc/dumpfile.h +++ b/gcc/dumpfile.h @@ -574,7 +574,7 @@ extern void dump_printf (const dump_metadata_t &, const char *, ...) extern void dump_printf_loc (const dump_metadata_t &, const dump_user_location_t &, const char *, ...) - ATTRIBUTE_GCC_DUMP_PRINTF (3, 0); + ATTRIBUTE_GCC_DUMP_PRINTF (3, 4); extern void dump_function (int phase, tree fn); extern void dump_basic_block (dump_flags_t, basic_block, int); extern void dump_generic_expr_loc (const dump_metadata_t &, diff --git a/gcc/dwarf2asm.cc b/gcc/dwarf2asm.cc index 274f574..7eac83f 100644 --- a/gcc/dwarf2asm.cc +++ b/gcc/dwarf2asm.cc @@ -35,10 +35,6 @@ along with GCC; see the file COPYING3. If not see #include "emit-rtl.h" #include "fold-const.h" -#ifndef XCOFF_DEBUGGING_INFO -#define XCOFF_DEBUGGING_INFO 0 -#endif - /* Output an unaligned integer with the given value and size. Prefer not to print a newline, since the caller may want to add a comment. */ @@ -384,16 +380,13 @@ dw2_asm_output_nstring (const char *str, size_t orig_len, if (flag_debug_asm && comment) { - if (XCOFF_DEBUGGING_INFO) - fputs ("\t.byte \"", asm_out_file); - else - fputs ("\t.ascii \"", asm_out_file); + fputs ("\t.ascii \"", asm_out_file); for (i = 0; i < len; i++) { int c = str[i]; if (c == '\"') - fputc (XCOFF_DEBUGGING_INFO ? '\"' : '\\', asm_out_file); + fputc ('\\', asm_out_file); else if (c == '\\') fputc ('\\', asm_out_file); if (ISPRINT (c)) @@ -913,7 +906,7 @@ static GTY(()) hash_map<const char *, tree> *indirect_pool; static GTY(()) int dw2_const_labelno; #if defined(HAVE_GAS_HIDDEN) -# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO) +# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY) #else # define USE_LINKONCE_INDIRECT 0 #endif diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index e3920c8..e418360 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -105,14 +105,6 @@ static rtx_insn *cached_next_real_insn; static void dwarf2out_decl (tree); static bool is_redundant_typedef (const_tree); -#ifndef XCOFF_DEBUGGING_INFO -#define XCOFF_DEBUGGING_INFO 0 -#endif - -#ifndef HAVE_XCOFF_DWARF_EXTRAS -#define HAVE_XCOFF_DWARF_EXTRAS 0 -#endif - #ifdef VMS_DEBUGGING_INFO int vms_file_stats_name (const char *, long long *, long *, char *, int *); @@ -608,14 +600,11 @@ output_fde (dw_fde_ref fde, bool for_eh, bool second, for_eh + j); ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j); ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j); - if (!XCOFF_DEBUGGING_INFO || for_eh) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh) - dw2_asm_output_data (4, 0xffffffff, "Initial length escape value" - " indicating 64-bit DWARF extension"); - dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1, - "FDE Length"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh) + dw2_asm_output_data (4, 0xffffffff, "Initial length escape value" + " indicating 64-bit DWARF extension"); + dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1, + "FDE Length"); ASM_OUTPUT_LABEL (asm_out_file, l1); if (for_eh) @@ -812,14 +801,11 @@ output_call_frame_info (int for_eh) /* Output the CIE. */ ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); - if (!XCOFF_DEBUGGING_INFO || for_eh) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1, - "Length of Common Information Entry"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4 && !for_eh) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_delta (for_eh ? 4 : dwarf_offset_size, l2, l1, + "Length of Common Information Entry"); ASM_OUTPUT_LABEL (asm_out_file, l1); /* Now that the CIE pointer is PC-relative for EH, @@ -3679,8 +3665,7 @@ static GTY (()) vec<macinfo_entry, va_gc> *macinfo_table; /* True if .debug_macinfo or .debug_macros section is going to be emitted. */ #define have_macinfo \ - ((!XCOFF_DEBUGGING_INFO || HAVE_XCOFF_DWARF_EXTRAS) \ - && debug_info_level >= DINFO_LEVEL_VERBOSE \ + (debug_info_level >= DINFO_LEVEL_VERBOSE \ && !macinfo_table->is_empty ()) /* Vector of dies for which we should generate .debug_ranges info. */ @@ -3865,7 +3850,7 @@ static int decl_quals (const_tree); static dw_die_ref modified_type_die (tree, int, bool, dw_die_ref); static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref); static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref); -static unsigned int dbx_reg_number (const_rtx); +static unsigned int debugger_reg_number (const_rtx); static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); static dw_loc_descr_ref reg_loc_descriptor (rtx, enum var_init_status); static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int, @@ -4982,9 +4967,6 @@ add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref { dw_attr_node attr; - if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS) - return; - attr.dw_attr = attr_kind; attr.dw_attr_val.val_class = dw_val_class_loc_list; attr.dw_attr_val.val_entry = NULL; @@ -5008,9 +4990,6 @@ add_AT_view_list (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_node attr; - if (XCOFF_DEBUGGING_INFO && !HAVE_XCOFF_DWARF_EXTRAS) - return; - attr.dw_attr = attr_kind; attr.dw_attr_val.val_class = dw_val_class_view_list; attr.dw_attr_val.val_entry = NULL; @@ -11166,15 +11145,12 @@ output_dwarf_version () static void output_compilation_unit_header (enum dwarf_unit_type ut) { - if (!XCOFF_DEBUGGING_INFO) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_data (dwarf_offset_size, - next_die_offset - DWARF_INITIAL_LENGTH_SIZE, - "Length of Compilation Unit Info"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (dwarf_offset_size, + next_die_offset - DWARF_INITIAL_LENGTH_SIZE, + "Length of Compilation Unit Info"); output_dwarf_version (); if (dwarf_version >= 5) @@ -11683,14 +11659,11 @@ output_pubnames (vec<pubname_entry, va_gc> *names) unsigned long pubnames_length = size_of_pubnames (names); pubname_entry *pub; - if (!XCOFF_DEBUGGING_INFO) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_data (dwarf_offset_size, pubnames_length, - "Pub Info Length"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (dwarf_offset_size, pubnames_length, + "Pub Info Length"); /* Version number for pubnames/pubtypes is independent of dwarf version. */ dw2_asm_output_data (2, 2, "DWARF pubnames/pubtypes version"); @@ -11765,14 +11738,11 @@ output_aranges (void) unsigned i; unsigned long aranges_length = size_of_aranges (); - if (!XCOFF_DEBUGGING_INFO) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_data (dwarf_offset_size, aranges_length, - "Length of Address Ranges Info"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (dwarf_offset_size, aranges_length, + "Length of Address Ranges Info"); /* Version number for aranges is still 2, even up to DWARF5. */ dw2_asm_output_data (2, 2, "DWARF aranges version"); @@ -13066,14 +13036,11 @@ output_line_info (bool prologue_only) ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, output_line_info_generation++); - if (!XCOFF_DEBUGGING_INFO) - { - if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) - dw2_asm_output_data (4, 0xffffffff, - "Initial length escape value indicating 64-bit DWARF extension"); - dw2_asm_output_delta (dwarf_offset_size, l2, l1, - "Length of Source Line Info"); - } + if (DWARF_INITIAL_LENGTH_SIZE - dwarf_offset_size == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_delta (dwarf_offset_size, l2, l1, + "Length of Source Line Info"); ASM_OUTPUT_LABEL (asm_out_file, l1); @@ -13210,6 +13177,7 @@ base_type_die (tree type, bool reverse) { const char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); if (strcmp (name, "char16_t") == 0 + || strcmp (name, "char8_t") == 0 || strcmp (name, "char32_t") == 0) { encoding = DW_ATE_UTF; @@ -14201,10 +14169,10 @@ template_parameter_pack_die (tree parm_pack, return die; } -/* Return the DBX register number described by a given RTL node. */ +/* Return the debugger register number described by a given RTL node. */ static unsigned int -dbx_reg_number (const_rtx rtl) +debugger_reg_number (const_rtx rtl) { unsigned regno = REGNO (rtl); @@ -14219,7 +14187,7 @@ dbx_reg_number (const_rtx rtl) } #endif - regno = DBX_REGISTER_NUMBER (regno); + regno = DEBUGGER_REGNO (regno); gcc_assert (regno != INVALID_REGNUM); return regno; } @@ -14282,10 +14250,10 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized) return multiple_reg_loc_descriptor (rtl, regs, initialized); else { - unsigned int dbx_regnum = dbx_reg_number (rtl); - if (dbx_regnum == IGNORED_DWARF_REGNUM) + unsigned int debugger_regnum = debugger_reg_number (rtl); + if (debugger_regnum == IGNORED_DWARF_REGNUM) return 0; - return one_reg_loc_descriptor (dbx_regnum, initialized); + return one_reg_loc_descriptor (debugger_regnum, initialized); } } @@ -14334,7 +14302,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs, } #endif - gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl)); + gcc_assert ((unsigned) DEBUGGER_REGNO (reg) == debugger_reg_number (rtl)); nregs = REG_NREGS (rtl); /* At present we only track constant-sized pieces. */ @@ -14347,7 +14315,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs, { dw_loc_descr_ref t; - t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg), + t = one_reg_loc_descriptor (DEBUGGER_REGNO (reg), VAR_INIT_STATUS_INITIALIZED); add_loc_descr (&loc_result, t); add_loc_descr_op_piece (&loc_result, size); @@ -14369,7 +14337,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs, { dw_loc_descr_ref t; - t = one_reg_loc_descriptor (dbx_reg_number (XVECEXP (regs, 0, i)), + t = one_reg_loc_descriptor (debugger_reg_number (XVECEXP (regs, 0, i)), VAR_INIT_STATUS_INITIALIZED); add_loc_descr (&loc_result, t); add_loc_descr_op_piece (&loc_result, size); @@ -16027,7 +15995,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode, )) { dw_die_ref type_die; - unsigned int dbx_regnum; + unsigned int debugger_regnum; if (dwarf_strict && dwarf_version < 5) break; @@ -16037,11 +16005,11 @@ mem_loc_descriptor (rtx rtl, machine_mode mode, if (type_die == NULL) break; - dbx_regnum = dbx_reg_number (rtl); - if (dbx_regnum == IGNORED_DWARF_REGNUM) + debugger_regnum = debugger_reg_number (rtl); + if (debugger_regnum == IGNORED_DWARF_REGNUM) break; mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_regval_type), - dbx_regnum, 0); + debugger_regnum, 0); mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_die_ref; mem_loc_result->dw_loc_oprnd2.v.val_die_ref.die = type_die; mem_loc_result->dw_loc_oprnd2.v.val_die_ref.external = 0; @@ -16312,10 +16280,10 @@ mem_loc_descriptor (rtx rtl, machine_mode mode, VOIDmode, VAR_INIT_STATUS_INITIALIZED); else { - unsigned int dbx_regnum = dbx_reg_number (ENTRY_VALUE_EXP (rtl)); - if (dbx_regnum == IGNORED_DWARF_REGNUM) + unsigned int debugger_regnum = debugger_reg_number (ENTRY_VALUE_EXP (rtl)); + if (debugger_regnum == IGNORED_DWARF_REGNUM) return NULL; - op0 = one_reg_loc_descriptor (dbx_regnum, + op0 = one_reg_loc_descriptor (debugger_regnum, VAR_INIT_STATUS_INITIALIZED); } } @@ -29143,8 +29111,6 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug) /* AIX Assembler inserts the length, so adjust the reference to match the offset expected by debuggers. */ strcpy (dl_section_ref, debug_line_label); - if (XCOFF_DEBUGGING_INFO) - strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR); /* For .debug_macro emit the section header. */ if (!dwarf_strict || dwarf_version >= 5) @@ -32349,8 +32315,6 @@ dwarf2out_finish (const char *filename) /* AIX Assembler inserts the length, so adjust the reference to match the offset expected by debuggers. */ strcpy (dl_section_ref, debug_line_section_label); - if (XCOFF_DEBUGGING_INFO) - strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR); if (debug_info_level >= DINFO_LEVEL_TERSE) add_AT_lineptr (main_comp_unit_die, DW_AT_stmt_list, @@ -33066,8 +33030,6 @@ dwarf2out_early_finish (const char *filename) /* AIX Assembler inserts the length, so adjust the reference to match the offset expected by debuggers. */ strcpy (dl_section_ref, debug_line_section_label); - if (XCOFF_DEBUGGING_INFO) - strcat (dl_section_ref, DWARF_INITIAL_LENGTH_SIZE_STR); if (debug_info_level >= DINFO_LEVEL_TERSE) add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list, dl_section_ref); diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc index 3929ee0..f25fb70 100644 --- a/gcc/emit-rtl.cc +++ b/gcc/emit-rtl.cc @@ -107,6 +107,8 @@ REAL_VALUE_TYPE dconst1; REAL_VALUE_TYPE dconst2; REAL_VALUE_TYPE dconstm1; REAL_VALUE_TYPE dconsthalf; +REAL_VALUE_TYPE dconstinf; +REAL_VALUE_TYPE dconstninf; /* Record fixed-point constant 0 and 1. */ FIXED_VALUE_TYPE fconst0[MAX_FCONST0]; @@ -6210,6 +6212,9 @@ init_emit_once (void) dconsthalf = dconst1; SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1); + real_inf (&dconstinf); + real_inf (&dconstninf, true); + for (i = 0; i < 3; i++) { const REAL_VALUE_TYPE *const r = diff --git a/gcc/except.cc b/gcc/except.cc index 7d7ce40..57064cf 100644 --- a/gcc/except.cc +++ b/gcc/except.cc @@ -2175,7 +2175,7 @@ expand_builtin_eh_return_data_regno (tree exp) #ifdef DWARF_FRAME_REGNUM iwhich = DWARF_FRAME_REGNUM (iwhich); #else - iwhich = DBX_REGISTER_NUMBER (iwhich); + iwhich = DEBUGGER_REGNO (iwhich); #endif return GEN_INT (iwhich); diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 8d7418b..6c02c3b 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -794,7 +794,7 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, words or to cope with mode punning between equal-sized modes. In the latter case, use subreg on the rhs side, not lhs. */ rtx sub; - HOST_WIDE_INT regnum; + poly_uint64 bytenum; poly_uint64 regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0)); if (known_eq (bitnum, 0U) && known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0)))) @@ -808,13 +808,13 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, return true; } } - else if (((constant_multiple_p (bitnum, regsize * BITS_PER_UNIT, ®num) - && multiple_p (bitsize, regsize * BITS_PER_UNIT)) - || undefined_p) + else if (multiple_p (bitnum, BITS_PER_UNIT, &bytenum) + && (undefined_p + || (multiple_p (bitnum, regsize * BITS_PER_UNIT) + && multiple_p (bitsize, regsize * BITS_PER_UNIT))) && known_ge (GET_MODE_BITSIZE (GET_MODE (op0)), bitsize)) { - sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), - regnum * regsize); + sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), bytenum); if (sub) { if (reverse) diff --git a/gcc/final.cc b/gcc/final.cc index 0352786..c0bfdf6 100644 --- a/gcc/final.cc +++ b/gcc/final.cc @@ -83,16 +83,8 @@ along with GCC; see the file COPYING3. If not see #include "function-abi.h" #include "common/common-target.h" -#ifdef XCOFF_DEBUGGING_INFO -#include "xcoffout.h" /* Needed for external data declarations. */ -#endif - #include "dwarf2out.h" -#ifdef DBX_DEBUGGING_INFO -#include "dbxout.h" -#endif - /* Most ports don't need to define CC_STATUS_INIT. So define a null default for it to save conditionalization later. */ #ifndef CC_STATUS_INIT @@ -2324,19 +2316,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1; BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p; } - if (write_symbols == DBX_DEBUG) - { - location_t *locus_ptr - = block_nonartificial_location (NOTE_BLOCK (insn)); - - if (locus_ptr != NULL) - { - override_filename = LOCATION_FILE (*locus_ptr); - override_linenum = LOCATION_LINE (*locus_ptr); - override_columnnum = LOCATION_COLUMN (*locus_ptr); - override_discriminator = compute_discriminator (*locus_ptr); - } - } break; case NOTE_INSN_BLOCK_END: @@ -2359,27 +2338,6 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) == in_cold_section_p); } - if (write_symbols == DBX_DEBUG) - { - tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn)); - location_t *locus_ptr - = block_nonartificial_location (outer_block); - - if (locus_ptr != NULL) - { - override_filename = LOCATION_FILE (*locus_ptr); - override_linenum = LOCATION_LINE (*locus_ptr); - override_columnnum = LOCATION_COLUMN (*locus_ptr); - override_discriminator = compute_discriminator (*locus_ptr); - } - else - { - override_filename = NULL; - override_linenum = 0; - override_columnnum = 0; - override_discriminator = 0; - } - } break; case NOTE_INSN_DELETED_LABEL: @@ -4304,8 +4262,6 @@ rest_of_handle_final (void) if (! quiet_flag) fflush (asm_out_file); - /* Write DBX symbols if requested. */ - /* Note that for those inline functions where we don't initially know for certain that we will be generating an out-of-line copy, the first invocation of this routine (rest_of_compilation) will diff --git a/gcc/flag-types.h b/gcc/flag-types.h index a11f99a..d2e7510 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -24,24 +24,18 @@ along with GCC; see the file COPYING3. If not see enum debug_info_type { - DINFO_TYPE_NONE = 0, /* No debug info. */ - DINFO_TYPE_DBX = 1, /* BSD .stabs for DBX. */ - DINFO_TYPE_DWARF2 = 2, /* Dwarf v2 debug info. */ - DINFO_TYPE_XCOFF = 3, /* IBM/Xcoff debug info. */ - DINFO_TYPE_VMS = 4, /* VMS debug info. */ - DINFO_TYPE_CTF = 5, /* CTF debug info. */ - DINFO_TYPE_BTF = 6, /* BTF debug info. */ - DINFO_TYPE_BTF_WITH_CORE = 7, /* BTF debug info with CO-RE relocations. */ + DINFO_TYPE_NONE, /* No debug info. */ + DINFO_TYPE_DWARF2, /* Dwarf v2 debug info. */ + DINFO_TYPE_VMS, /* VMS debug info. */ + DINFO_TYPE_CTF, /* CTF debug info. */ + DINFO_TYPE_BTF, /* BTF debug info. */ + DINFO_TYPE_BTF_WITH_CORE, /* BTF debug info with CO-RE relocations. */ DINFO_TYPE_MAX = DINFO_TYPE_BTF_WITH_CORE /* Marker only. */ }; #define NO_DEBUG (0U) -/* Write DBX debug info (using dbxout.cc). */ -#define DBX_DEBUG (1U << DINFO_TYPE_DBX) /* Write DWARF2 debug info (using dwarf2out.cc). */ #define DWARF2_DEBUG (1U << DINFO_TYPE_DWARF2) -/* Write IBM/XCOFF debug info (using dbxout.cc). */ -#define XCOFF_DEBUG (1U << DINFO_TYPE_XCOFF) /* Write VMS debug info (using vmsdbgout.cc). */ #define VMS_DEBUG (1U << DINFO_TYPE_VMS) /* Write CTF debug info (using ctfout.cc). */ diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index 6d7dc2e..7295387 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -952,6 +952,10 @@ fold_const_call_ss (wide_int *result, combined_fn fn, *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision); return true; + case CFN_BUILT_IN_ISSIGNALING: + *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision); + return true; + CASE_CFN_ISINF: case CFN_BUILT_IN_ISINFD32: case CFN_BUILT_IN_ISINFD64: @@ -1112,7 +1116,7 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag, CASE_CFN_CPROJ: if (real_isinf (arg_real) || real_isinf (arg_imag)) { - real_inf (result_real); + *result_real = dconstinf; *result_imag = dconst0; result_imag->sign = arg_imag->sign; } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 1352a54..e90248d 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,67 @@ +2022-09-04 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100136 + * trans-expr.cc (gfc_conv_procedure_call): Add handling of pointer + expressions. + +2022-09-03 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100245 + * trans-expr.cc (trans_class_assignment): Add if clause to handle + derived type in the LHS. + +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * trans-openmp.cc (gfc_trans_omp_clauses): Use + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE instead of + OMP_CLAUSE_DEPEND_SINK_NEGATIVE, build OMP_CLAUSE_DOACROSS + clause instead of OMP_CLAUSE_DEPEND and set OMP_CLAUSE_DOACROSS_DEPEND + on it. + +2022-09-02 Harald Anlauf <anlauf@gmx.de> + Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/99349 + * decl.cc (match_data_constant): Avoid NULL pointer dereference. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR fortran/106579 + * trans-intrinsic.cc: Include realmpfr.h. + (conv_intrinsic_ieee_value): New function. + (gfc_conv_ieee_arithmetic_function): Handle ieee_value. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR fortran/106579 + * f95-lang.cc (gfc_init_builtin_functions): Initialize + BUILT_IN_FPCLASSIFY. + * libgfortran.h (IEEE_OTHER_VALUE, IEEE_SIGNALING_NAN, + IEEE_QUIET_NAN, IEEE_NEGATIVE_INF, IEEE_NEGATIVE_NORMAL, + IEEE_NEGATIVE_DENORMAL, IEEE_NEGATIVE_SUBNORMAL, + IEEE_NEGATIVE_ZERO, IEEE_POSITIVE_ZERO, IEEE_POSITIVE_DENORMAL, + IEEE_POSITIVE_SUBNORMAL, IEEE_POSITIVE_NORMAL, IEEE_POSITIVE_INF): + New enum. + * trans-intrinsic.cc (conv_intrinsic_ieee_class): New function. + (gfc_conv_ieee_arithmetic_function): Handle ieee_class. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + * f95-lang.cc (gfc_init_builtin_functions): Initialize + BUILT_IN_ISSIGNALING. + +2022-08-25 Tobias Burnus <tobias@codesourcery.com> + + * parse.cc (parse_omp_structured_block): When parsing strictly + structured blocks, issue an error if the end-directive comes + before the 'end block'. + +2022-08-24 Harald Anlauf <anlauf@gmx.de> + + PR fortran/103694 + * simplify.cc (simplify_size): The size expression of an array cannot + be simplified if an error occurs while resolving the array spec. + 2022-08-22 Harald Anlauf <anlauf@gmx.de> PR fortran/106557 diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index b640051..0f9b2ce 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -423,7 +423,8 @@ match_data_constant (gfc_expr **result) data-pointer-initialization compatible (7.5.4.6) with the initial data target; the data statement object is initially associated with the target. */ - if ((*result)->symtree->n.sym->attr.save + if ((*result)->symtree + && (*result)->symtree->n.sym->attr.save && (*result)->symtree->n.sym->attr.target) return m; gfc_free_expr (*result); diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc index 319cf8f..10ac8a9 100644 --- a/gcc/fortran/f95-lang.cc +++ b/gcc/fortran/f95-lang.cc @@ -1013,10 +1013,13 @@ gfc_init_builtin_functions (void) "__builtin_isnan", ATTR_CONST_NOTHROW_LEAF_LIST); gfc_define_builtin ("__builtin_isnormal", ftype, BUILT_IN_ISNORMAL, "__builtin_isnormal", ATTR_CONST_NOTHROW_LEAF_LIST); + gfc_define_builtin ("__builtin_issignaling", ftype, BUILT_IN_ISSIGNALING, + "__builtin_issignaling", ATTR_CONST_NOTHROW_LEAF_LIST); gfc_define_builtin ("__builtin_signbit", ftype, BUILT_IN_SIGNBIT, "__builtin_signbit", ATTR_CONST_NOTHROW_LEAF_LIST); + gfc_define_builtin ("__builtin_fpclassify", ftype, BUILT_IN_FPCLASSIFY, + "__builtin_fpclassify", ATTR_CONST_NOTHROW_LEAF_LIST); - ftype = build_function_type (integer_type_node, NULL_TREE); gfc_define_builtin ("__builtin_isless", ftype, BUILT_IN_ISLESS, "__builtin_isless", ATTR_CONST_NOTHROW_LEAF_LIST); gfc_define_builtin ("__builtin_islessequal", ftype, BUILT_IN_ISLESSEQUAL, diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h index 4328447..ef06194 100644 --- a/gcc/fortran/libgfortran.h +++ b/gcc/fortran/libgfortran.h @@ -187,3 +187,23 @@ typedef enum BT_ASSUMED, BT_UNION, BT_BOZ } bt; + +/* Enumeration of the possible floating-point types. These values + correspond to the hidden arguments of the IEEE_CLASS_TYPE + derived-type of IEEE_ARITHMETIC. */ + +enum { + IEEE_OTHER_VALUE = 0, + IEEE_SIGNALING_NAN, + IEEE_QUIET_NAN, + IEEE_NEGATIVE_INF, + IEEE_NEGATIVE_NORMAL, + IEEE_NEGATIVE_DENORMAL, + IEEE_NEGATIVE_SUBNORMAL = IEEE_NEGATIVE_DENORMAL, + IEEE_NEGATIVE_ZERO, + IEEE_POSITIVE_ZERO, + IEEE_POSITIVE_DENORMAL, + IEEE_POSITIVE_SUBNORMAL = IEEE_POSITIVE_DENORMAL, + IEEE_POSITIVE_NORMAL, + IEEE_POSITIVE_INF +}; diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index 0b4c596..80492c9 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -5709,7 +5709,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } return st; } - else if (st != omp_end_st) + else if (st != omp_end_st || block_construct) { unexpected_statement (st); st = next_statement (); diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index f992c31..bc178d5 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -7536,8 +7536,9 @@ simplify_size (gfc_expr *array, gfc_expr *dim, int k) } for (ref = array->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY && ref->u.ar.as) - gfc_resolve_array_spec (ref->u.ar.as, 0); + if (ref->type == REF_ARRAY && ref->u.ar.as + && !gfc_resolve_array_spec (ref->u.ar.as, 0)) + return NULL; if (dim == NULL) { diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 850007f..7895d03 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -7220,16 +7220,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, else goto end_pointer_check; + tmp = parmse.expr; if (fsym && fsym->ts.type == BT_CLASS) { - tmp = build_fold_indirect_ref_loc (input_location, - parmse.expr); + if (POINTER_TYPE_P (TREE_TYPE (tmp))) + tmp = build_fold_indirect_ref_loc (input_location, tmp); tmp = gfc_class_data_get (tmp); if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) tmp = gfc_conv_descriptor_data_get (tmp); } - else - tmp = parmse.expr; /* If the argument is passed by value, we need to strip the INDIRECT_REF. */ @@ -11436,6 +11435,9 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, class_han = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr)) ? gfc_class_data_get (lse->expr) : lse->expr; + if (!POINTER_TYPE_P (TREE_TYPE (class_han))) + class_han = gfc_build_addr_expr (NULL_TREE, class_han); + /* Allocate block. */ gfc_init_block (&alloc); gfc_allocate_using_malloc (&alloc, class_han, size, NULL_TREE); diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 9d91278..ec116ff 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "trans-array.h" #include "dependency.h" /* For CAF array alias analysis. */ #include "attribs.h" +#include "realmpfr.h" /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */ @@ -10013,6 +10014,199 @@ conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr) } +/* Generate code for IEEE_CLASS. */ + +static void +conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr) +{ + tree arg, c, t1, t2, t3, t4; + + /* Convert arg, evaluate it only once. */ + conv_ieee_function_args (se, expr, &arg, 1); + arg = gfc_evaluate_now (arg, &se->pre); + + c = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6, + build_int_cst (integer_type_node, IEEE_QUIET_NAN), + build_int_cst (integer_type_node, + IEEE_POSITIVE_INF), + build_int_cst (integer_type_node, + IEEE_POSITIVE_NORMAL), + build_int_cst (integer_type_node, + IEEE_POSITIVE_DENORMAL), + build_int_cst (integer_type_node, + IEEE_POSITIVE_ZERO), + arg); + c = gfc_evaluate_now (c, &se->pre); + t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, + c, build_int_cst (integer_type_node, + IEEE_QUIET_NAN)); + t2 = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_ISSIGNALING), 1, + arg); + t2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node, + t2, build_zero_cst (TREE_TYPE (t2))); + t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR, + logical_type_node, t1, t2); + t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node, + c, build_int_cst (integer_type_node, + IEEE_POSITIVE_ZERO)); + t4 = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_SIGNBIT), 1, + arg); + t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node, + t4, build_zero_cst (TREE_TYPE (t4))); + t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR, + logical_type_node, t3, t4); + int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO; + gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF); + gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL); + gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL); + gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL); + gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO); + t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c), + build_int_cst (TREE_TYPE (c), s), c); + t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), + t3, t4, c); + t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1, + build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN), + t3); + tree type = gfc_typenode_for_spec (&expr->ts); + /* Perform a quick sanity check that the return type is + IEEE_CLASS_TYPE derived type defined in + libgfortran/ieee/ieee_arithmetic.F90 + Primarily check that it is a derived type with a single + member in it. */ + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + tree field = NULL_TREE; + for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + gcc_assert (field == NULL_TREE); + field = f; + } + gcc_assert (field); + t1 = fold_convert (TREE_TYPE (field), t1); + se->expr = build_constructor_single (type, field, t1); +} + + +/* Generate code for IEEE_VALUE. */ + +static void +conv_intrinsic_ieee_value (gfc_se *se, gfc_expr *expr) +{ + tree args[2], arg, ret, tmp; + stmtblock_t body; + + /* Convert args, evaluate the second one only once. */ + conv_ieee_function_args (se, expr, args, 2); + arg = gfc_evaluate_now (args[1], &se->pre); + + tree type = TREE_TYPE (arg); + /* Perform a quick sanity check that the second argument's type is + IEEE_CLASS_TYPE derived type defined in + libgfortran/ieee/ieee_arithmetic.F90 + Primarily check that it is a derived type with a single + member in it. */ + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + tree field = NULL_TREE; + for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f)) + if (TREE_CODE (f) == FIELD_DECL) + { + gcc_assert (field == NULL_TREE); + field = f; + } + gcc_assert (field); + arg = fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field), + arg, field, NULL_TREE); + arg = gfc_evaluate_now (arg, &se->pre); + + type = gfc_typenode_for_spec (&expr->ts); + gcc_assert (TREE_CODE (type) == REAL_TYPE); + ret = gfc_create_var (type, NULL); + + gfc_init_block (&body); + + tree end_label = gfc_build_label_decl (NULL_TREE); + for (int c = IEEE_SIGNALING_NAN; c <= IEEE_POSITIVE_INF; ++c) + { + tree label = gfc_build_label_decl (NULL_TREE); + tree low = build_int_cst (TREE_TYPE (arg), c); + tmp = build_case_label (low, low, label); + gfc_add_expr_to_block (&body, tmp); + + REAL_VALUE_TYPE real; + int k; + switch (c) + { + case IEEE_SIGNALING_NAN: + real_nan (&real, "", 0, TYPE_MODE (type)); + break; + case IEEE_QUIET_NAN: + real_nan (&real, "", 1, TYPE_MODE (type)); + break; + case IEEE_NEGATIVE_INF: + real_inf (&real); + real = real_value_negate (&real); + break; + case IEEE_NEGATIVE_NORMAL: + real_from_integer (&real, TYPE_MODE (type), -42, SIGNED); + break; + case IEEE_NEGATIVE_DENORMAL: + k = gfc_validate_kind (BT_REAL, expr->ts.kind, false); + real_from_mpfr (&real, gfc_real_kinds[k].tiny, + type, GFC_RND_MODE); + real_arithmetic (&real, RDIV_EXPR, &real, &dconst2); + real = real_value_negate (&real); + break; + case IEEE_NEGATIVE_ZERO: + real_from_integer (&real, TYPE_MODE (type), 0, SIGNED); + real = real_value_negate (&real); + break; + case IEEE_POSITIVE_ZERO: + /* Make this also the default: label. The other possibility + would be to add a separate default: label followed by + __builtin_unreachable (). */ + label = gfc_build_label_decl (NULL_TREE); + tmp = build_case_label (NULL_TREE, NULL_TREE, label); + gfc_add_expr_to_block (&body, tmp); + real_from_integer (&real, TYPE_MODE (type), 0, SIGNED); + break; + case IEEE_POSITIVE_DENORMAL: + k = gfc_validate_kind (BT_REAL, expr->ts.kind, false); + real_from_mpfr (&real, gfc_real_kinds[k].tiny, + type, GFC_RND_MODE); + real_arithmetic (&real, RDIV_EXPR, &real, &dconst2); + break; + case IEEE_POSITIVE_NORMAL: + real_from_integer (&real, TYPE_MODE (type), 42, SIGNED); + break; + case IEEE_POSITIVE_INF: + real_inf (&real); + break; + default: + gcc_unreachable (); + } + + tree val = build_real (type, real); + gfc_add_modify (&body, ret, val); + + tmp = build1_v (GOTO_EXPR, end_label); + gfc_add_expr_to_block (&body, tmp); + } + + tmp = gfc_finish_block (&body); + tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, arg, tmp); + gfc_add_expr_to_block (&se->pre, tmp); + + tmp = build1_v (LABEL_EXPR, end_label); + gfc_add_expr_to_block (&se->pre, tmp); + + se->expr = ret; +} + + /* Generate code for an intrinsic function from the IEEE_ARITHMETIC module. */ @@ -10043,6 +10237,10 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr) conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB); else if (startswith (name, "_gfortran_ieee_rint")) conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT); + else if (startswith (name, "ieee_class_") && ISDIGIT (name[11])) + conv_intrinsic_ieee_class (se, expr); + else if (startswith (name, "ieee_value_") && ISDIGIT (name[11])) + conv_intrinsic_ieee_value (se, expr); else /* It is not among the functions we translate directly. We return false, so a library function call is emitted. */ diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index de27ed5..82c1079 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2897,7 +2897,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, } vec = tree_cons (addend, t, vec); if (neg) - OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1; + OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; } if (n->next == NULL || n->next->u.depend_op != OMP_DEPEND_SINK) @@ -2908,8 +2908,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, continue; tree node = build_omp_clause (input_location, - OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK; + OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK; + OMP_CLAUSE_DOACROSS_DEPEND (node) = 1; OMP_CLAUSE_DECL (node) = nreverse (vec); omp_clauses = gfc_trans_add_clause (node, omp_clauses); continue; @@ -4254,8 +4255,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, if (clauses->depend_source) { - c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND); - OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE; + c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS); + OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE; + OMP_CLAUSE_DOACROSS_DEPEND (c) = 1; omp_clauses = gfc_trans_add_clause (c, omp_clauses); } diff --git a/gcc/function-tests.cc b/gcc/function-tests.cc index 1f983e8..68e8b97 100644 --- a/gcc/function-tests.cc +++ b/gcc/function-tests.cc @@ -627,25 +627,7 @@ test_expansion_to_rtl () (reg:SI 87 [ D.59 ])) -1 (nil)) (insn 10 6 11 2 (set (reg/i:SI 0 ax) (reg:SI 88 [ <retval> ])) -1 (nil)) - (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil)) - - On cr16-elf I get this: - (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) - (insn 2 4 3 2 (set (reg:SI 24) - (reg/f:SI 16 virtual-incoming-args)) -1 - (nil)) - (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) - (insn 6 3 7 2 (set (reg:HI 22 [ _1 ]) - (const_int 42 [0x2a])) -1 - (nil)) - (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ]) - (reg:HI 22 [ _1 ])) -1 - (nil)) - (insn 11 7 12 2 (set (reg/i:HI 0 r0) - (reg:HI 23 [ <retval> ])) -1 - (nil)) - (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1 - (nil)). */ + (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil)). */ verify_three_block_rtl_cfg (fun); /* Verify as much of the RTL as we can whilst avoiding diff --git a/gcc/function.cc b/gcc/function.cc index 31256b5..5498a71 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -4639,14 +4639,6 @@ number_blocks (tree fn) int n_blocks; tree *block_vector; - /* For XCOFF debugging output, we start numbering the blocks - from 1 within each function, rather than keeping a running - count. */ -#if defined (XCOFF_DEBUGGING_INFO) - if (write_symbols == XCOFF_DEBUG) - next_block_index = 1; -#endif - block_vector = get_block_vector (DECL_INITIAL (fn), &n_blocks); /* The top-level BLOCK isn't numbered at all. */ @@ -45,6 +45,7 @@ compilation is specified by a string called a "spec". */ #include "filenames.h" #include "spellcheck.h" #include "opts-jobserver.h" +#include "common/common-target.h" @@ -927,26 +928,11 @@ proper position among the other output files. */ # else # define ASM_DEBUG_DWARF_OPTION "--gdwarf2" # endif -# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \ - && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) -# define ASM_DEBUG_SPEC \ - (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ - ? "%{%:debug-level-gt(0):" \ - "%{gdwarf*:" ASM_DEBUG_DWARF_OPTION "};" \ - ":%{g*:--gstabs}}" ASM_MAP \ - : "%{%:debug-level-gt(0):" \ - "%{gstabs*:--gstabs;" \ - ":%{g*:" ASM_DEBUG_DWARF_OPTION "}}}" ASM_MAP) -# else -# if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG) -# define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):--gstabs}}" ASM_MAP -# endif # if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) # define ASM_DEBUG_SPEC "%{g*:%{%:debug-level-gt(0):" \ ASM_DEBUG_DWARF_OPTION "}}" ASM_MAP # endif # endif -#endif #ifndef ASM_DEBUG_SPEC # define ASM_DEBUG_SPEC "" #endif @@ -960,14 +946,7 @@ proper position among the other output files. */ "%:dwarf-version-gt(3):--gdwarf-4 ;" \ "%:dwarf-version-gt(2):--gdwarf-3 ;" \ ":--gdwarf2 }" -# if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) -# define ASM_DEBUG_OPTION_SPEC \ - (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG \ - ? "%{%:debug-level-gt(0):" \ - "%{gdwarf*:" ASM_DEBUG_OPTION_DWARF_OPT "}}" \ - : "%{%:debug-level-gt(0):" \ - "%{!gstabs*:%{g*:" ASM_DEBUG_OPTION_DWARF_OPT "}}}") -# elif defined(DWARF2_DEBUGGING_INFO) +# if defined(DWARF2_DEBUGGING_INFO) # define ASM_DEBUG_OPTION_SPEC "%{g*:%{%:debug-level-gt(0):" \ ASM_DEBUG_OPTION_DWARF_OPT "}}" # endif @@ -3585,42 +3564,6 @@ execute (void) } } -/* Find all the switches given to us - and make a vector describing them. - The elements of the vector are strings, one per switch given. - If a switch uses following arguments, then the `part1' field - is the switch itself and the `args' field - is a null-terminated vector containing the following arguments. - Bits in the `live_cond' field are: - SWITCH_LIVE to indicate this switch is true in a conditional spec. - SWITCH_FALSE to indicate this switch is overridden by a later switch. - SWITCH_IGNORE to indicate this switch should be ignored (used in %<S). - SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored. - SWITCH_KEEP_FOR_GCC to indicate that this switch, otherwise ignored, - should be included in COLLECT_GCC_OPTIONS. - in all do_spec calls afterwards. Used for %<S from self specs. - The `known' field describes whether this is an internal switch. - The `validated' field describes whether any spec has looked at this switch; - if it remains false at the end of the run, the switch must be meaningless. - The `ordering' field is used to temporarily mark switches that have to be - kept in a specific order. */ - -#define SWITCH_LIVE (1 << 0) -#define SWITCH_FALSE (1 << 1) -#define SWITCH_IGNORE (1 << 2) -#define SWITCH_IGNORE_PERMANENTLY (1 << 3) -#define SWITCH_KEEP_FOR_GCC (1 << 4) - -struct switchstr -{ - const char *part1; - const char **args; - unsigned int live_cond; - bool known; - bool validated; - bool ordering; -}; - static struct switchstr *switches; static int n_switches; @@ -9849,6 +9792,17 @@ set_multilib_dir (void) ++p; } + multilib_dir = + targetm_common.compute_multilib ( + switches, + n_switches, + multilib_dir, + multilib_defaults, + multilib_select, + multilib_matches, + multilib_exclusions, + multilib_reuse); + if (multilib_dir == NULL && multilib_os_dir != NULL && strcmp (multilib_os_dir, ".") == 0) { diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc index 6bcf6eb..b2e3c43 100644 --- a/gcc/gimple-loop-versioning.cc +++ b/gcc/gimple-loop-versioning.cc @@ -940,7 +940,7 @@ loop_versioning::analyze_term_using_scevs (address_info &address, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, address.stmt, - "looking through %G", assign); + "looking through %G", (gimple *) assign); stride = strip_casts (gimple_assign_rhs1 (assign)); } diff --git a/gcc/gimple-predicate-analysis.cc b/gcc/gimple-predicate-analysis.cc index ea81daa..a754ff0 100644 --- a/gcc/gimple-predicate-analysis.cc +++ b/gcc/gimple-predicate-analysis.cc @@ -41,6 +41,7 @@ #include "calls.h" #include "value-query.h" #include "cfganal.h" +#include "tree-eh.h" #include "gimple-predicate-analysis.h" @@ -59,33 +60,6 @@ for the case corresponding to an edge. */ #define MAX_SWITCH_CASES 40 -/* Return true if, when BB1 is postdominating BB2, BB1 is a loop exit. */ - -static bool -is_loop_exit (basic_block bb2, basic_block bb1) -{ - return single_pred_p (bb1) && !single_succ_p (bb2); -} - -/* Find BB's closest postdominator that is its control equivalent (i.e., - that's controlled by the same predicate). */ - -static inline basic_block -find_control_equiv_block (basic_block bb) -{ - basic_block pdom = get_immediate_dominator (CDI_POST_DOMINATORS, bb); - - /* Skip the postdominating bb that is also a loop exit. */ - if (is_loop_exit (bb, pdom)) - return NULL; - - /* If the postdominator is dominated by BB, return it. */ - if (dominated_by_p (CDI_DOMINATORS, pdom, bb)) - return pdom; - - return NULL; -} - /* Return true if X1 is the negation of X2. */ static inline bool @@ -149,10 +123,10 @@ format_edge_vec (const vec<edge> &ev) { char es[32]; const_edge e = ev[i]; - sprintf (es, "%u", e->src->index); + sprintf (es, "%u -> %u", e->src->index, e->dest->index); str += es; if (i + 1 < n) - str += " -> "; + str += ", "; } return str; } @@ -196,64 +170,14 @@ static void dump_pred_chain (const pred_chain &chain) { unsigned np = chain.length (); - if (np > 1) - fprintf (dump_file, "AND ("); - for (unsigned j = 0; j < np; j++) { + if (j > 0) + fprintf (dump_file, " AND ("); + else + fputc ('(', dump_file); dump_pred_info (chain[j]); - if (j < np - 1) - fprintf (dump_file, ", "); - else if (j > 0) - fputc (')', dump_file); - } -} - -/* Dump the predicate chain PREDS for STMT, prefixed by MSG. */ - -static void -dump_predicates (gimple *stmt, const pred_chain_union &preds, const char *msg) -{ - fprintf (dump_file, "%s", msg); - if (stmt) - { - print_gimple_stmt (dump_file, stmt, 0); - fprintf (dump_file, "is guarded by:\n"); - } - - unsigned np = preds.length (); - if (np > 1) - fprintf (dump_file, "OR ("); - for (unsigned i = 0; i < np; i++) - { - dump_pred_chain (preds[i]); - if (i < np - 1) - fprintf (dump_file, ", "); - else if (i > 0) - fputc (')', dump_file); - } - fputc ('\n', dump_file); -} - -/* Dump the first NCHAINS elements of the DEP_CHAINS array into DUMP_FILE. */ - -static void -dump_dep_chains (const auto_vec<edge> dep_chains[], unsigned nchains) -{ - if (!dump_file) - return; - - for (unsigned i = 0; i != nchains; ++i) - { - const auto_vec<edge> &v = dep_chains[i]; - unsigned n = v.length (); - for (unsigned j = 0; j != n; ++j) - { - fprintf (dump_file, "%u", v[j]->src->index); - if (j + 1 < n) - fprintf (dump_file, " -> "); - } - fputc ('\n', dump_file); + fputc (')', dump_file); } } @@ -483,19 +407,18 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def, Checking recursively into (1), the compiler can find out that only some_val (which is defined) can flow into (3) which is OK. */ -static bool -prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, - tree boundary_cst, tree_code cmp_code, - predicate::func_t &eval, - hash_set<gphi *> *visited_phis, - bitmap *visited_flag_phis) +bool +uninit_analysis::prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, + tree boundary_cst, tree_code cmp_code, + hash_set<gphi *> *visited_phis, + bitmap *visited_flag_phis) { /* The Boolean predicate guarding the PHI definition. Initialized lazily from PHI in the first call to is_use_guarded() and cached for subsequent iterations. */ - predicate def_preds (eval); + uninit_analysis def_preds (m_eval); - unsigned n = MIN (eval.max_phi_args, gimple_phi_num_args (flag_def)); + unsigned n = MIN (m_eval.max_phi_args, gimple_phi_num_args (flag_def)); for (unsigned i = 0; i < n; i++) { if (!MASK_TEST_BIT (opnds, i)) @@ -532,9 +455,9 @@ prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, bitmap_set_bit (*visited_flag_phis, SSA_NAME_VERSION (phi_result)); /* Now recursively try to prune the interesting phi args. */ - unsigned opnds_arg_phi = eval.phi_arg_set (phi_arg_def); + unsigned opnds_arg_phi = m_eval.phi_arg_set (phi_arg_def); if (!prune_phi_opnds (phi_arg_def, opnds_arg_phi, flag_arg_def, - boundary_cst, cmp_code, eval, visited_phis, + boundary_cst, cmp_code, visited_phis, visited_flag_phis)) return false; @@ -554,7 +477,7 @@ prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, gimple *opnd_def = SSA_NAME_DEF_STMT (opnd); if (gphi *opnd_def_phi = dyn_cast <gphi *> (opnd_def)) { - unsigned opnds2 = eval.phi_arg_set (opnd_def_phi); + unsigned opnds2 = m_eval.phi_arg_set (opnd_def_phi); if (!MASK_EMPTY (opnds2)) { edge opnd_edge = gimple_phi_arg_edge (phi, i); @@ -578,9 +501,10 @@ prune_phi_opnds (gphi *phi, unsigned opnds, gphi *flag_def, up the CFG nodes that it's dominated by. *EDGES holds the result, and VISITED is used for detecting cycles. */ -static void -collect_phi_def_edges (gphi *phi, basic_block cd_root, auto_vec<edge> *edges, - predicate::func_t &eval, hash_set<gimple *> *visited) +void +uninit_analysis::collect_phi_def_edges (gphi *phi, basic_block cd_root, + vec<edge> *edges, + hash_set<gimple *> *visited) { if (visited->elements () == 0 && DEBUG_PREDICATE_ANALYZER @@ -596,35 +520,13 @@ collect_phi_def_edges (gphi *phi, basic_block cd_root, auto_vec<edge> *edges, return; unsigned n = gimple_phi_num_args (phi); + unsigned opnds_arg_phi = m_eval.phi_arg_set (phi); for (unsigned i = 0; i < n; i++) { - edge opnd_edge = gimple_phi_arg_edge (phi, i); - tree opnd = gimple_phi_arg_def (phi, i); - - if (TREE_CODE (opnd) == SSA_NAME) - { - gimple *def = SSA_NAME_DEF_STMT (opnd); - - if (gimple_code (def) == GIMPLE_PHI - && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root)) - collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges, eval, - visited); - else if (!eval (opnd)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, - "\tFound def edge %i -> %i for cd_root %i " - "and operand %u of: ", - opnd_edge->src->index, opnd_edge->dest->index, - cd_root->index, i); - print_gimple_stmt (dump_file, phi, 0); - } - edges->safe_push (opnd_edge); - } - } - else + if (!MASK_TEST_BIT (opnds_arg_phi, i)) { + /* Add the edge for a not maybe-undefined edge value. */ + edge opnd_edge = gimple_phi_arg_edge (phi, i); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, @@ -634,62 +536,30 @@ collect_phi_def_edges (gphi *phi, basic_block cd_root, auto_vec<edge> *edges, cd_root->index, i); print_gimple_stmt (dump_file, phi, 0); } - - if (!eval (opnd)) - edges->safe_push (opnd_edge); + edges->safe_push (opnd_edge); + continue; } - } -} - -/* Return an expression corresponding to the predicate PRED. */ - -static tree -build_pred_expr (const pred_info &pred) -{ - tree_code cond_code = pred.cond_code; - tree lhs = pred.pred_lhs; - tree rhs = pred.pred_rhs; - - if (pred.invert) - cond_code = invert_tree_comparison (cond_code, false); - - return build2 (cond_code, TREE_TYPE (lhs), lhs, rhs); -} - -/* Return an expression corresponding to PREDS. */ - -static tree -build_pred_expr (const pred_chain_union &preds, bool invert = false) -{ - tree_code code = invert ? TRUTH_AND_EXPR : TRUTH_OR_EXPR; - tree_code subcode = invert ? TRUTH_OR_EXPR : TRUTH_AND_EXPR; - - tree expr = NULL_TREE; - for (unsigned i = 0; i != preds.length (); ++i) - { - tree subexpr = NULL_TREE; - for (unsigned j = 0; j != preds[i].length (); ++j) - { - const pred_info &pi = preds[i][j]; - tree cond = build_pred_expr (pi); - if (invert) - cond = invert_truthvalue (cond); - subexpr = subexpr ? build2 (subcode, boolean_type_node, - subexpr, cond) : cond; - } - if (expr) - expr = build2 (code, boolean_type_node, expr, subexpr); else - expr = subexpr; + { + tree opnd = gimple_phi_arg_def (phi, i); + if (TREE_CODE (opnd) == SSA_NAME) + { + gimple *def = SSA_NAME_DEF_STMT (opnd); + if (gimple_code (def) == GIMPLE_PHI + && dominated_by_p (CDI_DOMINATORS, gimple_bb (def), cd_root)) + /* Process PHI defs of maybe-undefined edge values + recursively. */ + collect_phi_def_edges (as_a<gphi *> (def), cd_root, edges, + visited); + } + } } - - return expr; } /* Return a bitset of all PHI arguments or zero if there are too many. */ unsigned -predicate::func_t::phi_arg_set (gphi *phi) +uninit_analysis::func_t::phi_arg_set (gphi *phi) { unsigned n = gimple_phi_num_args (phi); @@ -772,7 +642,8 @@ predicate::func_t::phi_arg_set (gphi *phi) checked. */ bool -predicate::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited) +uninit_analysis::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited, + const predicate &use_preds) { gimple *flag_def = NULL; tree boundary_cst = NULL_TREE; @@ -781,7 +652,7 @@ predicate::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited) /* Find within the common prefix of multiple predicate chains a predicate that is a comparison of a flag variable against a constant. */ - tree_code cmp_code = find_var_cmp_const (m_preds, phi, &flag_def, + tree_code cmp_code = find_var_cmp_const (use_preds.chain (), phi, &flag_def, &boundary_cst); if (cmp_code == ERROR_MARK) return true; @@ -790,7 +661,7 @@ predicate::overlap (gphi *phi, unsigned opnds, hash_set<gphi *> *visited) value that is in conflict with the use guard/predicate. */ gphi *phi_def = as_a<gphi *> (flag_def); bool all_pruned = prune_phi_opnds (phi, opnds, phi_def, boundary_cst, - cmp_code, m_eval, visited, + cmp_code, visited, &visited_flag_phis); if (visited_flag_phis) @@ -1070,11 +941,52 @@ simple_control_dep_chain (vec<edge>& chain, basic_block from, basic_block to) } } -static void -simple_control_dep_chain (vec<edge>& chain, basic_block from, edge to) +/* Perform a DFS walk on predecessor edges to mark the region denoted + by the EXIT edge and DOM which dominates EXIT->src, including DOM. + Blocks in the region are marked with FLAG and added to BBS. BBS is + filled up to its capacity only after which the walk is terminated + and false is returned. If the whole region was marked, true is returned. */ + +static bool +dfs_mark_dominating_region (edge exit, basic_block dom, int flag, + vec<basic_block> &bbs) { - chain.safe_push (to); - simple_control_dep_chain (chain, from, to->src); + if (exit->src == dom || exit->src->flags & flag) + return true; + if (!bbs.space (1)) + return false; + bbs.quick_push (exit->src); + exit->src->flags |= flag; + auto_vec<edge_iterator, 20> stack (bbs.allocated () - bbs.length () + 1); + stack.quick_push (ei_start (exit->src->preds)); + while (!stack.is_empty ()) + { + /* Look at the edge on the top of the stack. */ + edge_iterator ei = stack.last (); + basic_block src = ei_edge (ei)->src; + + /* Check if the edge source has been visited yet. */ + if (!(src->flags & flag)) + { + /* Mark the source if there's still space. If not, return early. */ + if (!bbs.space (1)) + return false; + src->flags |= flag; + bbs.quick_push (src); + + /* Queue its predecessors if we didn't reach DOM. */ + if (src != dom && EDGE_COUNT (src->preds) > 0) + stack.quick_push (ei_start (src->preds)); + } + else + { + if (!ei_one_before_end_p (ei)) + ei_next (&stack.last ()); + else + stack.pop (); + } + } + return true; } /* Recursively compute the control dependence chains (paths of edges) @@ -1092,8 +1004,12 @@ static bool compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, vec<edge> cd_chains[], unsigned *num_chains, vec<edge> &cur_cd_chain, unsigned *num_calls, - unsigned depth = 0) + unsigned in_region = 0, unsigned depth = 0) { + /* In our recursive calls this doesn't happen. */ + if (single_succ_p (dom_bb)) + return false; + if (*num_calls > (unsigned)param_uninit_control_dep_attempts) { if (dump_file) @@ -1119,18 +1035,6 @@ compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, fprintf (dump_file, "chain length exceeds 5: %u\n", cur_chain_len); } - for (unsigned i = 0; i < cur_chain_len; i++) - { - edge e = cur_cd_chain[i]; - /* Cycle detected. */ - if (e->src == dom_bb) - { - if (dump_file) - fprintf (dump_file, "cycle detected\n"); - return false; - } - } - if (DEBUG_PREDICATE_ANALYZER && dump_file) fprintf (dump_file, "%*s%s (dom_bb = %u, dep_bb = %u, cd_chains = { %s }, ...)\n", @@ -1145,13 +1049,27 @@ compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, FOR_EACH_EDGE (e, ei, dom_bb->succs) { int post_dom_check = 0; - if (e->flags & (EDGE_FAKE | EDGE_ABNORMAL)) + if (e->flags & (EDGE_FAKE | EDGE_ABNORMAL | EDGE_DFS_BACK)) continue; basic_block cd_bb = e->dest; cur_cd_chain.safe_push (e); while (!dominated_by_p (CDI_POST_DOMINATORS, dom_bb, cd_bb) - || is_loop_exit (dom_bb, cd_bb)) + /* We want to stop when the CFG merges back from the + branch in dom_bb. The post-dominance check alone + falls foul of the case of a loop exit test branch + where the path on the loop exit post-dominates + the branch block. + The following catches this but will not allow + exploring the post-dom path further. For the + outermost recursion this means we will fail to + reach dep_bb while for others it means at least + dropping the loop exit predicate from the path + which is problematic as it increases the domain + spanned by the resulting predicate. + See gcc.dg/uninit-pred-11.c for the first case + and PR106754 for the second. */ + || single_pred_p (cd_bb)) { if (cd_bb == dep_bb) { @@ -1166,15 +1084,26 @@ compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, break; } + /* If the dominating region has been marked avoid walking outside. */ + if (in_region != 0 && !(cd_bb->flags & in_region)) + break; + /* Check if DEP_BB is indirectly control-dependent on DOM_BB. */ - if (compute_control_dep_chain (cd_bb, dep_bb, cd_chains, - num_chains, cur_cd_chain, - num_calls, depth + 1)) + if (!single_succ_p (cd_bb) + && compute_control_dep_chain (cd_bb, dep_bb, cd_chains, + num_chains, cur_cd_chain, + num_calls, in_region, depth + 1)) { found_cd_chain = true; break; } + /* The post-dominator walk will reach a backedge only + from a forwarder, otherwise it should choose to exit + the SCC. */ + if (single_succ_p (cd_bb) + && single_succ_edge (cd_bb)->flags & EDGE_DFS_BACK) + break; cd_bb = get_immediate_dominator (CDI_POST_DOMINATORS, cd_bb); post_dom_check++; if (cd_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) @@ -1189,173 +1118,16 @@ compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, return found_cd_chain; } -/* Return true if PRED can be invalidated by any predicate in GUARD. */ - static bool -can_be_invalidated_p (const pred_info &pred, const pred_chain &guard) -{ - if (dump_file && dump_flags & TDF_DETAILS) - { - fprintf (dump_file, "Testing if predicate: "); - dump_pred_info (pred); - fprintf (dump_file, "\n...can be invalidated by a USE guard of: "); - dump_pred_chain (guard); - fputc ('\n', dump_file); - } - - unsigned n = guard.length (); - for (unsigned i = 0; i < n; ++i) - { - if (pred_neg_p (pred, guard[i])) - { - if (dump_file && dump_flags & TDF_DETAILS) - { - fprintf (dump_file, " Predicate invalidated by: "); - dump_pred_info (guard[i]); - fputc ('\n', dump_file); - } - return true; - } - } - - return false; -} - -/* Return true if all predicates in PREDS are invalidated by GUARD being - true. */ - -static bool -can_be_invalidated_p (const pred_chain_union &preds, const pred_chain &guard) -{ - if (preds.is_empty ()) - return false; - - if (dump_file && dump_flags & TDF_DETAILS) - dump_predicates (NULL, preds, - "Testing if anything here can be invalidated: "); - - for (unsigned i = 0; i < preds.length (); ++i) - { - const pred_chain &chain = preds[i]; - unsigned j; - for (j = 0; j < chain.length (); ++j) - if (can_be_invalidated_p (chain[j], guard)) - break; - - /* If we were unable to invalidate any predicate in C, then there - is a viable path from entry to the PHI where the PHI takes - an interesting value and continues to a use of the PHI. */ - if (j == chain.length ()) - return false; - } - return true; -} - -/* Return true if none of the PHI arguments in OPNDS is used given - the use guards in *THIS that guard the PHI's use. */ - -bool -predicate::use_cannot_happen (gphi *phi, unsigned opnds) +compute_control_dep_chain (basic_block dom_bb, const_basic_block dep_bb, + vec<edge> cd_chains[], unsigned *num_chains, + unsigned in_region = 0) { - if (!m_eval.phi_arg_set (phi)) - return false; - - /* PHI_USE_GUARDS are OR'ed together. If we have more than one - possible guard, there's no way of knowing which guard was true. - In that case compute the intersection of all use predicates - and use that. */ - const pred_chain_union &phi_use_guards = m_preds; - const pred_chain *use_guard = &phi_use_guards[0]; - pred_chain phi_use_guard_intersection = vNULL; - if (phi_use_guards.length () != 1) - { - phi_use_guard_intersection = use_guard->copy (); - for (unsigned i = 1; i < phi_use_guards.length (); ++i) - { - for (unsigned j = 0; j < phi_use_guard_intersection.length ();) - { - unsigned k; - for (k = 0; k < phi_use_guards[i].length (); ++k) - if (pred_equal_p (phi_use_guards[i][k], - phi_use_guard_intersection[j])) - break; - if (k == phi_use_guards[i].length ()) - phi_use_guard_intersection.unordered_remove (j); - else - j++; - } - } - if (phi_use_guard_intersection.is_empty ()) - { - phi_use_guard_intersection.release (); - return false; - } - use_guard = &phi_use_guard_intersection; - } - - basic_block phi_bb = gimple_bb (phi); - /* Find the closest dominating bb to be the control dependence root. */ - basic_block cd_root = get_immediate_dominator (CDI_DOMINATORS, phi_bb); - if (!cd_root) - return false; - - /* Look for the control dependencies of all the interesting operands - and build guard predicates describing them. */ - unsigned n = gimple_phi_num_args (phi); - for (unsigned i = 0; i < n; ++i) - { - if (!MASK_TEST_BIT (opnds, i)) - continue; - - edge e = gimple_phi_arg_edge (phi, i); - auto_vec<edge> dep_chains[MAX_NUM_CHAINS]; - auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain; - unsigned num_chains = 0; - unsigned num_calls = 0; - - /* Build the control dependency chain for the PHI argument... */ - if (!compute_control_dep_chain (cd_root, - e->src, dep_chains, &num_chains, - cur_chain, &num_calls)) - { - gcc_assert (num_chains == 0); - /* If compute_control_dep_chain bailed out due to limits - build a partial sparse path using dominators. Collect - only edges whose predicates are always true when reaching E. */ - simple_control_dep_chain (dep_chains[0], - ENTRY_BLOCK_PTR_FOR_FN (cfun), e); - num_chains++; - } - - if (DEBUG_PREDICATE_ANALYZER && dump_file) - { - fprintf (dump_file, "predicate::use_cannot_happen (...) " - "dep_chains for arg %u:\n\t", i); - dump_dep_chains (dep_chains, num_chains); - } - - /* ...and convert it into a set of predicates guarding its - definition. */ - predicate def_preds (m_eval); - def_preds.init_from_control_deps (dep_chains, num_chains); - if (def_preds.is_empty ()) - /* If there's no predicate there's no basis to rule the use out. */ - return false; - - def_preds.simplify (); - def_preds.normalize (); - - /* Can the guard for this PHI argument be negated by the one - guarding the PHI use? */ - if (!can_be_invalidated_p (def_preds.chain (), *use_guard)) - { - phi_use_guard_intersection.release (); - return false; - } - } - - phi_use_guard_intersection.release (); - return true; + auto_vec<edge, MAX_CHAIN_LEN + 1> cur_cd_chain; + unsigned num_calls = 0; + unsigned depth = 0; + return compute_control_dep_chain (dom_bb, dep_bb, cd_chains, num_chains, + cur_cd_chain, &num_calls, in_region, depth); } /* Implemented simplifications: @@ -1688,303 +1460,6 @@ predicate::simplify (gimple *use_or_def, bool is_use) (_2 RELOP1 _1) AND (_5 RELOP2 _4) AND (_8 RELOP3 _7) AND (_0 != 0) */ -/* Store a PRED in *THIS. */ - -void -predicate::push_pred (const pred_info &pred) -{ - pred_chain chain = vNULL; - chain.safe_push (pred); - m_preds.safe_push (chain); -} - -/* Dump predicates in *THIS for STMT prepended by MSG. */ - -void -predicate::dump (gimple *stmt, const char *msg) const -{ - fprintf (dump_file, "%s", msg); - if (stmt) - { - fputc ('\t', dump_file); - print_gimple_stmt (dump_file, stmt, 0); - fprintf (dump_file, " is conditional on:\n"); - } - - unsigned np = m_preds.length (); - if (np == 0) - { - fprintf (dump_file, "\t(empty)\n"); - return; - } - - { - tree expr = build_pred_expr (m_preds); - char *str = print_generic_expr_to_str (expr); - fprintf (dump_file, "\t%s (expanded)\n", str); - free (str); - } - - if (np > 1) - fprintf (dump_file, "\tOR ("); - else - fputc ('\t', dump_file); - for (unsigned i = 0; i < np; i++) - { - dump_pred_chain (m_preds[i]); - if (i < np - 1) - fprintf (dump_file, ", "); - else if (i > 0) - fputc (')', dump_file); - } - fputc ('\n', dump_file); -} - -/* Initialize *THIS with the predicates of the control dependence chains - between the basic block DEF_BB that defines a variable of interst and - USE_BB that uses the variable, respectively. */ - -predicate::predicate (basic_block def_bb, basic_block use_bb, func_t &eval) - : m_preds (vNULL), m_eval (eval) -{ - /* Set CD_ROOT to the basic block closest to USE_BB that is the control - equivalent of (is guarded by the same predicate as) DEF_BB that also - dominates USE_BB. */ - basic_block cd_root = def_bb; - while (dominated_by_p (CDI_DOMINATORS, use_bb, cd_root)) - { - /* Find CD_ROOT's closest postdominator that's its control - equivalent. */ - if (basic_block bb = find_control_equiv_block (cd_root)) - if (dominated_by_p (CDI_DOMINATORS, use_bb, bb)) - { - cd_root = bb; - continue; - } - - break; - } - - /* Set DEP_CHAINS to the set of edges between CD_ROOT and USE_BB. - Each DEP_CHAINS element is a series of edges whose conditions - are logical conjunctions. Together, the DEP_CHAINS vector is - used below to initialize an OR expression of the conjunctions. */ - unsigned num_calls = 0; - unsigned num_chains = 0; - auto_vec<edge> dep_chains[MAX_NUM_CHAINS]; - auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain; - - if (!compute_control_dep_chain (cd_root, use_bb, dep_chains, &num_chains, - cur_chain, &num_calls)) - { - gcc_assert (num_chains == 0); - simple_control_dep_chain (dep_chains[0], cd_root, use_bb); - num_chains++; - } - - if (DEBUG_PREDICATE_ANALYZER && dump_file) - { - fprintf (dump_file, "predicate::predicate (def_bb = %u, use_bb = %u, func_t) " - "initialized from %u dep_chains:\n\t", - def_bb->index, use_bb->index, num_chains); - dump_dep_chains (dep_chains, num_chains); - } - - /* From the set of edges computed above initialize *THIS as the OR - condition under which the definition in DEF_BB is used in USE_BB. - Each OR subexpression is represented by one element of DEP_CHAINS, - where each element consists of a series of AND subexpressions. */ - init_from_control_deps (dep_chains, num_chains); -} - -/* Release resources in *THIS. */ - -predicate::~predicate () -{ - unsigned n = m_preds.length (); - for (unsigned i = 0; i != n; ++i) - m_preds[i].release (); - m_preds.release (); -} - -/* Copy-assign RHS to *THIS. */ - -predicate& -predicate::operator= (const predicate &rhs) -{ - if (this == &rhs) - return *this; - - /* FIXME: Make this a compile-time constraint? */ - gcc_assert (&m_eval == &rhs.m_eval); - - unsigned n = m_preds.length (); - for (unsigned i = 0; i != n; ++i) - m_preds[i].release (); - m_preds.release (); - - n = rhs.m_preds.length (); - for (unsigned i = 0; i != n; ++i) - { - const pred_chain &chain = rhs.m_preds[i]; - m_preds.safe_push (chain.copy ()); - } - - return *this; -} - -/* For each use edge of PHI, compute all control dependence chains - and convert those to the composite predicates in M_PREDS. - Return true if a nonempty predicate has been obtained. */ - -bool -predicate::init_from_phi_def (gphi *phi) -{ - gcc_assert (is_empty ()); - - basic_block phi_bb = gimple_bb (phi); - /* Find the closest dominating bb to be the control dependence root. */ - basic_block cd_root = get_immediate_dominator (CDI_DOMINATORS, phi_bb); - if (!cd_root) - return false; - - /* Set DEF_EDGES to the edges to the PHI from the bb's that provide - definitions of each of the PHI operands for which M_EVAL is false. */ - auto_vec<edge> def_edges; - hash_set<gimple *> visited_phis; - collect_phi_def_edges (phi, cd_root, &def_edges, m_eval, &visited_phis); - - unsigned nedges = def_edges.length (); - if (nedges == 0) - return false; - - unsigned num_chains = 0; - auto_vec<edge> dep_chains[MAX_NUM_CHAINS]; - auto_vec<edge, MAX_CHAIN_LEN + 1> cur_chain; - for (unsigned i = 0; i < nedges; i++) - { - edge e = def_edges[i]; - unsigned num_calls = 0; - unsigned prev_nc = num_chains; - compute_control_dep_chain (cd_root, e->src, dep_chains, - &num_chains, cur_chain, &num_calls); - - /* Update the newly added chains with the phi operand edge. */ - if (EDGE_COUNT (e->src->succs) > 1) - { - if (prev_nc == num_chains && num_chains < MAX_NUM_CHAINS) - dep_chains[num_chains++] = vNULL; - for (unsigned j = prev_nc; j < num_chains; j++) - dep_chains[j].safe_push (e); - } - } - - /* Convert control dependence chains to the predicate in *THIS under - which the PHI operands are defined to values for which M_EVAL is - false. */ - init_from_control_deps (dep_chains, num_chains); - return !is_empty (); -} - -/* Compute the predicates that guard the use USE_STMT and check if - the incoming paths that have an empty (or possibly empty) definition - can be pruned. Return true if it can be determined that the use of - PHI's def in USE_STMT is guarded by a predicate set that does not - overlap with the predicate sets of all runtime paths that do not - have a definition. - - Return false if the use is not guarded or if it cannot be determined. - USE_BB is the bb of the use (for phi operand use, the bb is not the bb - of the phi stmt, but the source bb of the operand edge). - - OPNDS is a bitmap with a bit set for each PHI operand of interest. - - THIS->M_PREDS contains the (memoized) defining predicate chains of - a PHI. If THIS->M_PREDS is empty, the PHI's defining predicate - chains are computed and stored into THIS->M_PREDS as needed. - - VISITED_PHIS is a pointer set of phis being visited. */ - -bool -predicate::is_use_guarded (gimple *use_stmt, basic_block use_bb, - gphi *phi, unsigned opnds, - hash_set<gphi *> *visited) -{ - if (visited->add (phi)) - return false; - - /* The basic block where the PHI is defined. */ - basic_block def_bb = gimple_bb (phi); - - /* Try to build the predicate expression under which the PHI flows - into its use. This will be empty if the PHI is defined and used - in the same bb. */ - predicate use_preds (def_bb, use_bb, m_eval); - - if (dominated_by_p (CDI_POST_DOMINATORS, def_bb, use_bb)) - { - if (is_empty ()) - { - /* Lazily initialize *THIS from the PHI and build its use - expression. */ - init_from_phi_def (phi); - } - - /* The use is not guarded. */ - return false; - } - - if (use_preds.is_empty ()) - return false; - - /* Try to prune the dead incoming phi edges. */ - if (!use_preds.overlap (phi, opnds, visited)) - { - if (DEBUG_PREDICATE_ANALYZER && dump_file) - fputs ("found predicate overlap\n", dump_file); - - return true; - } - - /* We might be able to prove that if the control dependencies for OPNDS - are true, the control dependencies for USE_STMT can never be true. */ - if (use_preds.use_cannot_happen (phi, opnds)) - return true; - - if (is_empty ()) - { - /* Lazily initialize *THIS from PHI. */ - if (!init_from_phi_def (phi)) - { - return false; - } - - simplify (phi); - normalize (phi); - } - - use_preds.simplify (use_stmt, /*is_use=*/true); - use_preds.normalize (use_stmt, /*is_use=*/true); - - /* Return true if the predicate guarding the valid definition (i.e., - *THIS) is a superset of the predicate guarding the use (i.e., - USE_PREDS). */ - if (superset_of (use_preds)) - return true; - - return false; -} - -/* Public interface to the above. */ - -bool -predicate::is_use_guarded (gimple *stmt, basic_block use_bb, gphi *phi, - unsigned opnds) -{ - hash_set<gphi *> visited; - return is_use_guarded (stmt, use_bb, phi, opnds, &visited); -} - /* Normalize predicate PRED: 1) if PRED can no longer be normalized, append it to *THIS. 2) otherwise if PRED is of the form x != 0, follow x's definition @@ -2148,7 +1623,7 @@ predicate::normalize (const pred_chain &chain) while (!work_list.is_empty ()) { pred_info pi = work_list.pop (); - predicate pred (m_eval); + predicate pred; /* The predicate object is not modified here, only NORM_CHAIN and WORK_LIST are appended to. */ pred.normalize (&norm_chain, pi, BIT_AND_EXPR, &work_list, &mark_set); @@ -2169,7 +1644,7 @@ predicate::normalize (gimple *use_or_def, bool is_use) dump (use_or_def, is_use ? "[USE]:\n" : "[DEF]:\n"); } - predicate norm_preds (m_eval); + predicate norm_preds; for (unsigned i = 0; i < m_preds.length (); i++) { if (m_preds[i].length () != 1) @@ -2198,20 +1673,17 @@ predicate::normalize (gimple *use_or_def, bool is_use) void predicate::init_from_control_deps (const vec<edge> *dep_chains, - unsigned num_chains) + unsigned num_chains, bool is_use) { gcc_assert (is_empty ()); - bool has_valid_pred = false; if (num_chains == 0) return; - if (num_chains >= MAX_NUM_CHAINS) - { - if (dump_file) - fprintf (dump_file, "MAX_NUM_CHAINS exceeded: %u\n", num_chains); - return; - } + if (DEBUG_PREDICATE_ANALYZER && dump_file) + fprintf (dump_file, "init_from_control_deps [%s] {%s}:\n", + is_use ? "USE" : "DEF", + format_edge_vecs (dep_chains, num_chains).c_str ()); /* Convert the control dependency chain into a set of predicates. */ m_preds.reserve (num_chains); @@ -2222,32 +1694,22 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains, of the predicates. */ const vec<edge> &path = dep_chains[i]; - has_valid_pred = false; + bool has_valid_pred = false; /* The chain of predicates guarding the definition along this path. */ pred_chain t_chain{ }; for (unsigned j = 0; j < path.length (); j++) { edge e = path[j]; basic_block guard_bb = e->src; - /* Ignore empty forwarder blocks. */ - if (empty_block_p (guard_bb) && single_succ_p (guard_bb)) - continue; - /* An empty basic block here is likely a PHI, and is not one - of the cases we handle below. */ - gimple_stmt_iterator gsi = gsi_last_bb (guard_bb); - if (gsi_end_p (gsi)) - { - has_valid_pred = false; - break; - } - /* Get the conditional controlling the bb exit edge. */ - gimple *cond_stmt = gsi_stmt (gsi); - if (is_gimple_call (cond_stmt) && EDGE_COUNT (e->src->succs) >= 2) - /* Ignore EH edge. Can add assertion on the other edge's flag. */ - continue; - /* Skip if there is essentially one succesor. */ - if (EDGE_COUNT (e->src->succs) == 2) + gcc_assert (!empty_block_p (guard_bb) && !single_succ_p (guard_bb)); + + /* Skip this edge if it is bypassing an abort - when the + condition is not satisfied we are neither reaching the + definition nor the use so it isn't meaningful. Note if + we are processing the use predicate the condition is + meaningful. See PR65244. */ + if (!is_use && EDGE_COUNT (e->src->succs) == 2) { edge e1; edge_iterator ei1; @@ -2262,8 +1724,13 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains, } } if (skip) - continue; + { + has_valid_pred = true; + continue; + } } + /* Get the conditional controlling the bb exit edge. */ + gimple *cond_stmt = last_stmt (guard_bb); if (gimple_code (cond_stmt) == GIMPLE_COND) { /* The true edge corresponds to the uninteresting condition. @@ -2279,7 +1746,8 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains, if (DEBUG_PREDICATE_ANALYZER && dump_file) { - fprintf (dump_file, "one_pred = "); + fprintf (dump_file, "%d -> %d: one_pred = ", + e->src->index, e->dest->index); dump_pred_info (one_pred); fputc ('\n', dump_file); } @@ -2288,73 +1756,383 @@ predicate::init_from_control_deps (const vec<edge> *dep_chains, } else if (gswitch *gs = dyn_cast<gswitch *> (cond_stmt)) { - /* Avoid quadratic behavior. */ - if (gimple_switch_num_labels (gs) > MAX_SWITCH_CASES) - { - has_valid_pred = false; - break; - } - /* Find the case label. */ tree l = NULL_TREE; - unsigned idx; - for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx) + /* Find the case label, but avoid quadratic behavior. */ + if (gimple_switch_num_labels (gs) <= MAX_SWITCH_CASES) + for (unsigned idx = 0; + idx < gimple_switch_num_labels (gs); ++idx) + { + tree tl = gimple_switch_label (gs, idx); + if (e->dest == label_to_block (cfun, CASE_LABEL (tl))) + { + if (!l) + l = tl; + else + { + l = NULL_TREE; + break; + } + } + } + /* If more than one label reaches this block or the case + label doesn't have a contiguous range of values (like the + default one) fail. */ + if (!l || !CASE_LOW (l)) + has_valid_pred = false; + else if (!CASE_HIGH (l) + || operand_equal_p (CASE_LOW (l), CASE_HIGH (l))) { - tree tl = gimple_switch_label (gs, idx); - if (e->dest == label_to_block (cfun, CASE_LABEL (tl))) - { - if (!l) - l = tl; - else - { - l = NULL_TREE; - break; - } - } + pred_info one_pred; + one_pred.pred_lhs = gimple_switch_index (gs); + one_pred.pred_rhs = CASE_LOW (l); + one_pred.cond_code = EQ_EXPR; + one_pred.invert = false; + t_chain.safe_push (one_pred); + has_valid_pred = true; } - /* If more than one label reaches this block or the case - label doesn't have a single value (like the default one) - fail. */ - if (!l - || !CASE_LOW (l) - || (CASE_HIGH (l) - && !operand_equal_p (CASE_LOW (l), CASE_HIGH (l), 0))) + else { - has_valid_pred = false; - break; + /* Support a case label with a range with + two predicates. We're overcommitting on + the MAX_CHAIN_LEN budget by at most a factor + of two here. */ + pred_info one_pred; + one_pred.pred_lhs = gimple_switch_index (gs); + one_pred.pred_rhs = CASE_LOW (l); + one_pred.cond_code = GE_EXPR; + one_pred.invert = false; + t_chain.safe_push (one_pred); + one_pred.pred_rhs = CASE_HIGH (l); + one_pred.cond_code = LE_EXPR; + t_chain.safe_push (one_pred); + has_valid_pred = true; } - - pred_info one_pred; - one_pred.pred_lhs = gimple_switch_index (gs); - one_pred.pred_rhs = CASE_LOW (l); - one_pred.cond_code = EQ_EXPR; - one_pred.invert = false; - t_chain.safe_push (one_pred); - has_valid_pred = true; } + else if (stmt_can_throw_internal (cfun, cond_stmt) + && !(e->flags & EDGE_EH)) + /* Ignore the exceptional control flow and proceed as if + E were a fallthru without a controlling predicate for + both the USE (valid) and DEF (questionable) case. */ + has_valid_pred = true; else - { - /* Disabled. See PR 90994. - has_valid_pred = false; */ - break; - } + has_valid_pred = false; + + /* For USE predicates we can drop components of the + AND chain. */ + if (!has_valid_pred && !is_use) + break; } - if (!has_valid_pred) - break; + /* For DEF predicates we have to drop components of the OR chain + on failure. */ + if (!has_valid_pred && !is_use) + { + t_chain.release (); + continue; + } + + /* When we add || 1 simply prune the chain and return. */ + if (t_chain.is_empty ()) + { + t_chain.release (); + for (auto chain : m_preds) + chain.release (); + m_preds.truncate (0); + break; + } + + m_preds.quick_push (t_chain); + } + + if (DEBUG_PREDICATE_ANALYZER && dump_file) + dump (NULL, ""); +} + +/* Store a PRED in *THIS. */ + +void +predicate::push_pred (const pred_info &pred) +{ + pred_chain chain = vNULL; + chain.safe_push (pred); + m_preds.safe_push (chain); +} + +/* Dump predicates in *THIS for STMT prepended by MSG. */ + +void +predicate::dump (gimple *stmt, const char *msg) const +{ + fprintf (dump_file, "%s", msg); + if (stmt) + { + fputc ('\t', dump_file); + print_gimple_stmt (dump_file, stmt, 0); + fprintf (dump_file, " is conditional on:\n"); + } + + unsigned np = m_preds.length (); + if (np == 0) + { + fprintf (dump_file, "\tTRUE (empty)\n"); + return; + } + + for (unsigned i = 0; i < np; i++) + { + if (i > 0) + fprintf (dump_file, "\tOR ("); else - m_preds.safe_push (t_chain); + fprintf (dump_file, "\t("); + dump_pred_chain (m_preds[i]); + fprintf (dump_file, ")\n"); + } +} + +/* Initialize USE_PREDS with the predicates of the control dependence chains + between the basic block DEF_BB that defines a variable of interst and + USE_BB that uses the variable, respectively. */ + +bool +uninit_analysis::init_use_preds (predicate &use_preds, basic_block def_bb, + basic_block use_bb) +{ + gcc_assert (use_preds.is_empty () + && dominated_by_p (CDI_DOMINATORS, use_bb, def_bb)); + + /* Set CD_ROOT to the basic block closest to USE_BB that is the control + equivalent of (is guarded by the same predicate as) DEF_BB that also + dominates USE_BB. This mimics the inner loop in + compute_control_dep_chain. */ + basic_block cd_root = def_bb; + do + { + basic_block pdom = get_immediate_dominator (CDI_POST_DOMINATORS, cd_root); + + /* Stop at a loop exit which is also postdominating cd_root. */ + if (single_pred_p (pdom) && !single_succ_p (cd_root)) + break; + + if (!dominated_by_p (CDI_DOMINATORS, pdom, cd_root) + || !dominated_by_p (CDI_DOMINATORS, use_bb, pdom)) + break; + + cd_root = pdom; + } + while (1); + + /* Set DEP_CHAINS to the set of edges between CD_ROOT and USE_BB. + Each DEP_CHAINS element is a series of edges whose conditions + are logical conjunctions. Together, the DEP_CHAINS vector is + used below to initialize an OR expression of the conjunctions. */ + unsigned num_chains = 0; + auto_vec<edge> dep_chains[MAX_NUM_CHAINS]; + + if (!compute_control_dep_chain (cd_root, use_bb, dep_chains, &num_chains)) + { + gcc_assert (num_chains == 0); + simple_control_dep_chain (dep_chains[0], cd_root, use_bb); + num_chains++; } if (DEBUG_PREDICATE_ANALYZER && dump_file) + fprintf (dump_file, "init_use_preds (def_bb = %u, use_bb = %u)\n", + def_bb->index, use_bb->index); + + /* From the set of edges computed above initialize *THIS as the OR + condition under which the definition in DEF_BB is used in USE_BB. + Each OR subexpression is represented by one element of DEP_CHAINS, + where each element consists of a series of AND subexpressions. */ + use_preds.init_from_control_deps (dep_chains, num_chains, true); + return !use_preds.is_empty (); +} + +/* Release resources in *THIS. */ + +predicate::~predicate () +{ + unsigned n = m_preds.length (); + for (unsigned i = 0; i != n; ++i) + m_preds[i].release (); + m_preds.release (); +} + +/* Copy-assign RHS to *THIS. */ + +predicate& +predicate::operator= (const predicate &rhs) +{ + if (this == &rhs) + return *this; + + unsigned n = m_preds.length (); + for (unsigned i = 0; i != n; ++i) + m_preds[i].release (); + m_preds.release (); + + n = rhs.m_preds.length (); + for (unsigned i = 0; i != n; ++i) { - fprintf (dump_file, "init_from_control_deps {%s}:\n", - format_edge_vecs (dep_chains, num_chains).c_str ()); - dump (NULL, ""); + const pred_chain &chain = rhs.m_preds[i]; + m_preds.safe_push (chain.copy ()); } - if (has_valid_pred) - gcc_assert (m_preds.length () != 0); - else - /* Clear M_PREDS to indicate failure. */ - m_preds.release (); + return *this; } + +/* For each use edge of PHI, compute all control dependence chains + and convert those to the composite predicates in M_PREDS. + Return true if a nonempty predicate has been obtained. */ + +bool +uninit_analysis::init_from_phi_def (gphi *phi) +{ + gcc_assert (m_phi_def_preds.is_empty ()); + + basic_block phi_bb = gimple_bb (phi); + /* Find the closest dominating bb to be the control dependence root. */ + basic_block cd_root = get_immediate_dominator (CDI_DOMINATORS, phi_bb); + if (!cd_root) + return false; + + /* Set DEF_EDGES to the edges to the PHI from the bb's that provide + definitions of each of the PHI operands for which M_EVAL is false. */ + auto_vec<edge> def_edges; + hash_set<gimple *> visited_phis; + collect_phi_def_edges (phi, cd_root, &def_edges, &visited_phis); + + unsigned nedges = def_edges.length (); + if (nedges == 0) + return false; + + auto_bb_flag in_region (cfun); + auto_vec<basic_block, 20> region (MIN (n_basic_blocks_for_fn (cfun), + param_uninit_control_dep_attempts)); + /* Pre-mark the PHI incoming edges PHI block to make sure we only walk + interesting edges from there. */ + for (unsigned i = 0; i < nedges; i++) + { + if (!(def_edges[i]->dest->flags & in_region)) + { + if (!region.space (1)) + break; + def_edges[i]->dest->flags |= in_region; + region.quick_push (def_edges[i]->dest); + } + } + for (unsigned i = 0; i < nedges; i++) + if (!dfs_mark_dominating_region (def_edges[i], cd_root, in_region, region)) + break; + + unsigned num_chains = 0; + auto_vec<edge> dep_chains[MAX_NUM_CHAINS]; + for (unsigned i = 0; i < nedges; i++) + { + edge e = def_edges[i]; + unsigned prev_nc = num_chains; + compute_control_dep_chain (cd_root, e->src, dep_chains, + &num_chains, in_region); + + /* Update the newly added chains with the phi operand edge. */ + if (EDGE_COUNT (e->src->succs) > 1) + { + if (prev_nc == num_chains && num_chains < MAX_NUM_CHAINS) + dep_chains[num_chains++] = vNULL; + for (unsigned j = prev_nc; j < num_chains; j++) + dep_chains[j].safe_push (e); + } + } + + /* Unmark the region. */ + for (auto bb : region) + bb->flags &= ~in_region; + + /* Convert control dependence chains to the predicate in *THIS under + which the PHI operands are defined to values for which M_EVAL is + false. */ + m_phi_def_preds.init_from_control_deps (dep_chains, num_chains, false); + return !m_phi_def_preds.is_empty (); +} + +/* Compute the predicates that guard the use USE_STMT and check if + the incoming paths that have an empty (or possibly empty) definition + can be pruned. Return true if it can be determined that the use of + PHI's def in USE_STMT is guarded by a predicate set that does not + overlap with the predicate sets of all runtime paths that do not + have a definition. + + Return false if the use is not guarded or if it cannot be determined. + USE_BB is the bb of the use (for phi operand use, the bb is not the bb + of the phi stmt, but the source bb of the operand edge). + + OPNDS is a bitmap with a bit set for each PHI operand of interest. + + THIS->M_PREDS contains the (memoized) defining predicate chains of + a PHI. If THIS->M_PREDS is empty, the PHI's defining predicate + chains are computed and stored into THIS->M_PREDS as needed. + + VISITED_PHIS is a pointer set of phis being visited. */ + +bool +uninit_analysis::is_use_guarded (gimple *use_stmt, basic_block use_bb, + gphi *phi, unsigned opnds, + hash_set<gphi *> *visited) +{ + if (visited->add (phi)) + return false; + + /* The basic block where the PHI is defined. */ + basic_block def_bb = gimple_bb (phi); + + if (dominated_by_p (CDI_POST_DOMINATORS, def_bb, use_bb)) + /* The use is not guarded. */ + return false; + + /* Try to build the predicate expression under which the PHI flows + into its use. This will be empty if the PHI is defined and used + in the same bb. */ + predicate use_preds; + if (!init_use_preds (use_preds, def_bb, use_bb)) + return false; + + use_preds.simplify (use_stmt, /*is_use=*/true); + use_preds.normalize (use_stmt, /*is_use=*/true); + + /* Try to prune the dead incoming phi edges. */ + if (!overlap (phi, opnds, visited, use_preds)) + { + if (DEBUG_PREDICATE_ANALYZER && dump_file) + fputs ("found predicate overlap\n", dump_file); + + return true; + } + + if (m_phi_def_preds.is_empty ()) + { + /* Lazily initialize *THIS from PHI. */ + if (!init_from_phi_def (phi)) + return false; + + m_phi_def_preds.simplify (phi); + m_phi_def_preds.normalize (phi); + } + + /* Return true if the predicate guarding the valid definition (i.e., + *THIS) is a superset of the predicate guarding the use (i.e., + USE_PREDS). */ + if (m_phi_def_preds.superset_of (use_preds)) + return true; + + return false; +} + +/* Public interface to the above. */ + +bool +uninit_analysis::is_use_guarded (gimple *stmt, basic_block use_bb, gphi *phi, + unsigned opnds) +{ + hash_set<gphi *> visited; + return is_use_guarded (stmt, use_bb, phi, opnds, &visited); +} + diff --git a/gcc/gimple-predicate-analysis.h b/gcc/gimple-predicate-analysis.h index 7767229..bc0248d 100644 --- a/gcc/gimple-predicate-analysis.h +++ b/gcc/gimple-predicate-analysis.h @@ -44,37 +44,11 @@ typedef vec<pred_chain, va_heap, vl_ptr> pred_chain_union; class predicate { public: - /* Base function object type used to determine whether an expression - is of interest. */ - struct func_t - { - typedef unsigned phi_arg_set_t; - - /* Return true if the argument is an expression of interest. */ - virtual bool operator()(tree) = 0; - /* Return a bitset of PHI arguments of interest. By default returns - bitset with a bit set for each argument. Should be called in - the overriden function first and, if nonzero, the result then - refined as appropriate. */ - virtual phi_arg_set_t phi_arg_set (gphi *); - - /* Maximum number of PHI arguments supported by phi_arg_set(). */ - static constexpr unsigned max_phi_args = - sizeof (phi_arg_set_t) * CHAR_BIT; - }; - /* Construct with the specified EVAL object. */ - predicate (func_t &eval) - : m_preds (vNULL), m_eval (eval) { } + predicate () : m_preds (vNULL) { } /* Copy. */ - predicate (const predicate &rhs) - : m_preds (vNULL), m_eval (rhs.m_eval) - { - *this = rhs; - } - - predicate (basic_block, basic_block, func_t &); + predicate (const predicate &rhs) : m_preds (vNULL) { *this = rhs; } ~predicate (); @@ -91,34 +65,23 @@ class predicate return m_preds; } - /* Return true if the use by a statement in the basic block of - a PHI operand is ruled out (i.e., guarded) by *THIS. */ - bool is_use_guarded (gimple *, basic_block, gphi *, unsigned); - - void init_from_control_deps (const vec<edge> *, unsigned); + void init_from_control_deps (const vec<edge> *, unsigned, bool); void dump (gimple *, const char *) const; void normalize (gimple * = NULL, bool = false); void simplify (gimple * = NULL, bool = false); - bool is_use_guarded (gimple *, basic_block, gphi *, unsigned, - hash_set<gphi *> *); - -private: - bool includes (const pred_chain &) const; bool superset_of (const predicate &) const; - bool overlap (gphi *, unsigned, hash_set<gphi *> *); - bool use_cannot_happen (gphi *, unsigned); - bool init_from_phi_def (gphi *); +private: + bool includes (const pred_chain &) const; void push_pred (const pred_info &); /* Normalization functions. */ void normalize (pred_chain *, pred_info, tree_code, pred_chain *, hash_set<tree> *); - void normalize (const pred_info &); void normalize (const pred_chain &); @@ -127,9 +90,60 @@ private: bool simplify_3 (); bool simplify_4 (); -private: /* Representation of the predicate expression(s). */ pred_chain_union m_preds; +}; + +/* Represents a complex Boolean predicate expression. */ +class uninit_analysis +{ + public: + /* Base function object type used to determine whether an expression + is of interest. */ + struct func_t + { + typedef unsigned phi_arg_set_t; + + /* Return a bitset of PHI arguments of interest. By default returns + bitset with a bit set for each argument. Should be called in + the overriden function first and, if nonzero, the result then + refined as appropriate. */ + virtual phi_arg_set_t phi_arg_set (gphi *); + + /* Maximum number of PHI arguments supported by phi_arg_set(). */ + static constexpr unsigned max_phi_args = + sizeof (phi_arg_set_t) * CHAR_BIT; + }; + + /* Construct with the specified EVAL object. */ + uninit_analysis (func_t &eval) + : m_phi_def_preds (), m_eval (eval) { } + + /* Copy. */ + uninit_analysis (const uninit_analysis &rhs) = delete; + + /* Assign. */ + uninit_analysis& operator= (const uninit_analysis&) = delete; + + /* Return true if the use by a statement in the basic block of + a PHI operand is ruled out (i.e., guarded) by *THIS. */ + bool is_use_guarded (gimple *, basic_block, gphi *, unsigned); + +private: + bool is_use_guarded (gimple *, basic_block, gphi *, unsigned, + hash_set<gphi *> *); + bool prune_phi_opnds (gphi *, unsigned, gphi *, tree, tree_code, + hash_set<gphi *> *, bitmap *); + bool overlap (gphi *, unsigned, hash_set<gphi *> *, const predicate &); + + void collect_phi_def_edges (gphi *, basic_block, vec<edge> *, + hash_set<gimple *> *); + bool init_from_phi_def (gphi *); + bool init_use_preds (predicate &, basic_block, basic_block); + + + /* Representation of the predicate expression(s). */ + predicate m_phi_def_preds; /* Callback to evaluate an operand. Return true if it's interesting. */ func_t &m_eval; }; diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index b0b2210..d8497fc 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -1023,6 +1023,26 @@ fold_using_range::range_of_builtin_int_call (irange &r, gcall *call, break; } + case CFN_BUILT_IN_SIGNBIT: + { + arg = gimple_call_arg (call, 0); + frange tmp; + if (src.get_operand (tmp, arg)) + { + if (tmp.get_signbit ().varying_p ()) + return false; + if (tmp.get_signbit ().yes_p ()) + { + tree one = build_one_cst (type); + r.set (one, one); + } + else + r.set_zero (type); + return true; + } + break; + } + case CFN_BUILT_IN_TOUPPER: { arg = gimple_call_arg (call, 0); diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index f9e7060..988fc93 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -6031,6 +6031,21 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, return GS_ALL_DONE; } + /* Convert initialization from an empty variable-size CONSTRUCTOR to + memset. */ + if (TREE_TYPE (*from_p) != error_mark_node + && TYPE_SIZE_UNIT (TREE_TYPE (*from_p)) + && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p))) + && TREE_CODE (*from_p) == CONSTRUCTOR + && CONSTRUCTOR_NELTS (*from_p) == 0) + { + maybe_with_size_expr (from_p); + gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR); + return gimplify_modify_expr_to_memset (expr_p, + TREE_OPERAND (*from_p, 1), + want_value, pre_p); + } + /* Insert pointer conversions required by the middle-end that are not required by the frontend. This fixes middle-end type checking for for example gcc.dg/redecl-6.c. */ @@ -8304,9 +8319,6 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p) case OMP_CLAUSE_DEPEND_INOUTSET: i = 4; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - continue; default: gcc_unreachable (); } @@ -8545,9 +8557,6 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p) case OMP_CLAUSE_DEPEND_INOUTSET: i = 4; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - continue; default: gcc_unreachable (); } @@ -10391,8 +10400,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, gimplify_omp_affinity (list_p, pre_p); remove = true; break; - case OMP_CLAUSE_DEPEND: - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + case OMP_CLAUSE_DOACROSS: + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { tree deps = OMP_CLAUSE_DECL (c); while (deps && TREE_CODE (deps) == TREE_LIST) @@ -10403,10 +10412,12 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, pre_p, NULL, is_gimple_val, fb_rvalue); deps = TREE_CHAIN (deps); } - break; } - else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) - break; + else + gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c) + == OMP_CLAUSE_DOACROSS_SOURCE); + break; + case OMP_CLAUSE_DEPEND: if (handled_depend_iterators == -1) handled_depend_iterators = gimplify_omp_depend (list_p, pre_p); if (handled_depend_iterators) @@ -11931,6 +11942,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_SAFELEN: case OMP_CLAUSE_SIMDLEN: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_PRIORITY: case OMP_CLAUSE_GRAINSIZE: case OMP_CLAUSE_NUM_TASKS: @@ -12414,6 +12426,29 @@ gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p, OMP_FOR_CLAUSES (orig_for_stmt) = c; } +/* Helper function of gimplify_omp_for, find OMP_ORDERED with + OMP_CLAUSE_DOACROSS clause inside of OMP_FOR's body. */ + +static tree +find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *) +{ + switch (TREE_CODE (*tp)) + { + case OMP_ORDERED: + if (omp_find_clause (OMP_ORDERED_CLAUSES (*tp), OMP_CLAUSE_DOACROSS)) + return *tp; + break; + case OMP_SIMD: + case OMP_PARALLEL: + case OMP_TARGET: + *walk_subtrees = 0; + break; + default: + break; + } + return NULL_TREE; +} + /* Gimplify the gross structure of an OMP_FOR statement. */ static enum gimplify_status @@ -12789,12 +12824,24 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED); bool is_doacross = false; - if (c && OMP_CLAUSE_ORDERED_EXPR (c)) + if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt), + find_standalone_omp_ordered, NULL)) { + OMP_CLAUSE_ORDERED_DOACROSS (c) = 1; is_doacross = true; - gimplify_omp_ctxp->loop_iter_var.create (TREE_VEC_LENGTH - (OMP_FOR_INIT (for_stmt)) - * 2); + int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); + gimplify_omp_ctxp->loop_iter_var.create (len * 2); + for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; ) + if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR) + { + error_at (OMP_CLAUSE_LOCATION (*pc), + "%<linear%> clause may not be specified together " + "with %<ordered%> clause if stand-alone %<ordered%> " + "construct is nested in it"); + *pc = OMP_CLAUSE_CHAIN (*pc); + } + else + pc = &OMP_CLAUSE_CHAIN (*pc); } int collapse = 1, tile = 0; c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE); @@ -14867,21 +14914,22 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (gimplify_omp_ctxp) { for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && gimplify_omp_ctxp->loop_iter_var.is_empty () - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && gimplify_omp_ctxp->loop_iter_var.is_empty ()) { error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause must be " - "closely nested inside a loop with %<ordered%> clause " - "with a parameter"); + "%<ordered%> construct with %qs clause must be " + "closely nested inside a loop with %<ordered%> clause", + OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross"); failures++; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { bool fail = false; + sink_c = c; + if (OMP_CLAUSE_DECL (c) == NULL_TREE) + continue; /* omp_cur_iteration - 1 */ for (decls = OMP_CLAUSE_DECL (c), i = 0; decls && TREE_CODE (decls) == TREE_LIST; decls = TREE_CHAIN (decls), ++i) @@ -14904,21 +14952,24 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2) { error_at (OMP_CLAUSE_LOCATION (c), - "number of variables in %<depend%> clause with " + "number of variables in %qs clause with " "%<sink%> modifier does not match number of " - "iteration variables"); + "iteration variables", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); failures++; } - sink_c = c; } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE) { if (source_c) { error_at (OMP_CLAUSE_LOCATION (c), - "more than one %<depend%> clause with %<source%> " - "modifier on an %<ordered%> construct"); + "more than one %qs clause with %<source%> " + "modifier on an %<ordered%> construct", + OMP_CLAUSE_DOACROSS_DEPEND (source_c) + ? "depend" : "doacross"); failures++; } else @@ -14928,9 +14979,11 @@ gimplify_omp_ordered (tree expr, gimple_seq body) if (source_c && sink_c) { error_at (OMP_CLAUSE_LOCATION (source_c), - "%<depend%> clause with %<source%> modifier specified " - "together with %<depend%> clauses with %<sink%> modifier " - "on the same construct"); + "%qs clause with %<source%> modifier specified " + "together with %qs clauses with %<sink%> modifier " + "on the same construct", + OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross", + OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross"); failures++; } diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index 79e296d..315ff78 100644 --- a/gcc/ginclude/stddef.h +++ b/gcc/ginclude/stddef.h @@ -443,6 +443,14 @@ typedef struct { #endif #endif /* C++11. */ +#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) +#ifndef _GCC_NULLPTR_T +#define _GCC_NULLPTR_T + typedef __typeof__(nullptr) nullptr_t; +/* ??? This doesn't define __STDC_VERSION_STDDEF_H__ yet. */ +#endif +#endif /* C23. */ + #endif /* _STDDEF_H was defined this time */ #endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__ diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 5dbcb29..c3f3da1 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,9 @@ +2022-09-02 Martin Liska <mliska@suse.cz> + + * go-lang.cc (go_langhook_pushdecl): Remove -gstabs option support, DBX-related + macros and DBX debugging info support. + * gospec.cc (lang_specific_driver): Likewise. + 2022-07-16 Ian Lance Taylor <iant@golang.org> * go-gcc.cc (Gcc_backend::struct_field_expression): Handle a void diff --git a/gcc/go/go-lang.cc b/gcc/go/go-lang.cc index 84cd623..d519a69 100644 --- a/gcc/go/go-lang.cc +++ b/gcc/go/go-lang.cc @@ -507,8 +507,7 @@ go_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) } /* This hook is used to get the current list of declarations as trees. - We don't support that; instead we use the write_globals hook. This - can't simply crash because it is called by -gstabs. */ + We don't support that; instead we use the write_globals hook. */ static tree go_langhook_getdecls (void) diff --git a/gcc/go/gospec.cc b/gcc/go/gospec.cc index df92b62..1e51407 100644 --- a/gcc/go/gospec.cc +++ b/gcc/go/gospec.cc @@ -215,11 +215,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, case OPT_gdwarf: case OPT_gdwarf_: case OPT_ggdb: - case OPT_gstabs: - case OPT_gstabs_: case OPT_gvms: - case OPT_gxcoff: - case OPT_gxcoff_: saw_opt_g = true; break; diff --git a/gcc/graphds.cc b/gcc/graphds.cc index 91a2ca5..2a108fd 100644 --- a/gcc/graphds.cc +++ b/gcc/graphds.cc @@ -281,7 +281,14 @@ graphds_dfs (struct graph *g, int *qs, int nq, vec<int> *qt, numbers assigned by the previous pass. If SUBGRAPH is not NULL, it specifies the subgraph of G whose strongly connected components we want to determine. If SKIP_EDGE_P is not NULL, it points to a callback function. - Edge E will be skipped if callback function returns true. + Edge E will be skipped if callback function returns true. If SCC_GROUPING + is not null, the nodes will be added to it in the following order: + + - If SCC A is a direct or indirect predecessor of SCC B in the SCC dag, + A's nodes come before B's nodes. + + - All of an SCC's nodes are listed consecutively, although the order + of the nodes within an SCC is not really meaningful. After running this function, v->component is the number of the strongly connected component for each vertex of G. Returns the number of the @@ -289,7 +296,7 @@ graphds_dfs (struct graph *g, int *qs, int nq, vec<int> *qt, int graphds_scc (struct graph *g, bitmap subgraph, - skip_edge_callback skip_edge_p) + skip_edge_callback skip_edge_p, vec<int> *scc_grouping) { int *queue = XNEWVEC (int, g->n_vertices); vec<int> postorder = vNULL; @@ -317,7 +324,7 @@ graphds_scc (struct graph *g, bitmap subgraph, for (i = 0; i < nq; i++) queue[i] = postorder[nq - i - 1]; - comp = graphds_dfs (g, queue, nq, NULL, true, subgraph, skip_edge_p); + comp = graphds_dfs (g, queue, nq, scc_grouping, true, subgraph, skip_edge_p); free (queue); postorder.release (); diff --git a/gcc/graphds.h b/gcc/graphds.h index c54d876..e0e4d80 100644 --- a/gcc/graphds.h +++ b/gcc/graphds.h @@ -58,7 +58,8 @@ void identify_vertices (struct graph *, int, int); typedef bool (*skip_edge_callback) (struct graph_edge *); int graphds_dfs (struct graph *, int *, int, vec<int> *, bool, bitmap, skip_edge_callback = NULL); -int graphds_scc (struct graph *, bitmap, skip_edge_callback = NULL); +int graphds_scc (struct graph *, bitmap, skip_edge_callback = NULL, + vec<int> * = NULL); void graphds_domtree (struct graph *, int, int *, int *, int *); typedef void (*graphds_edge_callback) (struct graph *, struct graph_edge *, void *); diff --git a/gcc/gstab.h b/gcc/gstab.h deleted file mode 100644 index c597d12..0000000 --- a/gcc/gstab.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 1997-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#ifndef GCC_GSTAB_H -#define GCC_GSTAB_H - -#define __define_stab(NAME, CODE, STRING) NAME=CODE, - -enum -{ -#include "stab.def" -LAST_UNUSED_STAB_CODE -}; - -/* stabs debug codes really are integers with expressive names. */ -typedef int stab_code_type; - -#undef __define_stab - -#endif /* ! GCC_GSTAB_H */ diff --git a/gcc/hash-map-traits.h b/gcc/hash-map-traits.h index fad0c7d..d729d35 100644 --- a/gcc/hash-map-traits.h +++ b/gcc/hash-map-traits.h @@ -105,14 +105,19 @@ struct simple_cache_map_traits: public simple_hashmap_traits<H,Value> static const bool maybe_mx = false; }; -/* Implement traits for a hash_map with values of type Value for cases - in which the key cannot represent empty and deleted slots. Instead - record empty and deleted entries in Value. Derived classes must - implement the hash and equal_keys functions. */ +/* Implement traits for a hash_map with keys of type Key and values of + type Value for cases in which the key cannot represent empty and + deleted slots. Instead record empty and deleted entries in Value. */ -template <typename Value> +template <typename Key, typename Value> struct unbounded_hashmap_traits { + typedef typename Key::value_type key_type; + + static hashval_t hash (const typename Key::value_type &); + static bool equal_keys (const typename Key::value_type &, + const typename Key::compare_type &); + template <typename T> static inline void remove (T &); static const bool empty_zero_p = default_hash_traits <Value>::empty_zero_p; template <typename T> static inline bool is_empty (const T &); @@ -121,42 +126,59 @@ struct unbounded_hashmap_traits template <typename T> static inline void mark_deleted (T &); }; -template <typename Value> +template <typename Key, typename Value> +inline hashval_t +unbounded_hashmap_traits <Key, Value> +::hash (const typename Key::value_type &key) +{ + return Key::hash (key); +} + +template <typename Key, typename Value> +inline bool +unbounded_hashmap_traits <Key, Value> +::equal_keys (const typename Key::value_type &x, + const typename Key::compare_type &y) +{ + return Key::equal (x, y); +} + +template <typename Key, typename Value> template <typename T> inline void -unbounded_hashmap_traits <Value>::remove (T &entry) +unbounded_hashmap_traits <Key, Value>::remove (T &entry) { default_hash_traits <Value>::remove (entry.m_value); } -template <typename Value> +template <typename Key, typename Value> template <typename T> inline bool -unbounded_hashmap_traits <Value>::is_empty (const T &entry) +unbounded_hashmap_traits <Key, Value>::is_empty (const T &entry) { return default_hash_traits <Value>::is_empty (entry.m_value); } -template <typename Value> +template <typename Key, typename Value> template <typename T> inline bool -unbounded_hashmap_traits <Value>::is_deleted (const T &entry) +unbounded_hashmap_traits <Key, Value>::is_deleted (const T &entry) { return default_hash_traits <Value>::is_deleted (entry.m_value); } -template <typename Value> +template <typename Key, typename Value> template <typename T> inline void -unbounded_hashmap_traits <Value>::mark_empty (T &entry) +unbounded_hashmap_traits <Key, Value>::mark_empty (T &entry) { default_hash_traits <Value>::mark_empty (entry.m_value); } -template <typename Value> +template <typename Key, typename Value> template <typename T> inline void -unbounded_hashmap_traits <Value>::mark_deleted (T &entry) +unbounded_hashmap_traits <Key, Value>::mark_deleted (T &entry) { default_hash_traits <Value>::mark_deleted (entry.m_value); } @@ -166,25 +188,7 @@ unbounded_hashmap_traits <Value>::mark_deleted (T &entry) slots. */ template <typename Key, typename Value> -struct unbounded_int_hashmap_traits : unbounded_hashmap_traits <Value> -{ - typedef Key key_type; - static inline hashval_t hash (Key); - static inline bool equal_keys (Key, Key); -}; - -template <typename Key, typename Value> -inline hashval_t -unbounded_int_hashmap_traits <Key, Value>::hash (Key k) -{ - return k; -} - -template <typename Key, typename Value> -inline bool -unbounded_int_hashmap_traits <Key, Value>::equal_keys (Key k1, Key k2) -{ - return k1 == k2; -} +using unbounded_int_hashmap_traits + = unbounded_hashmap_traits <int_hash_base <Key>, Value>; #endif // HASH_MAP_TRAITS_H diff --git a/gcc/hash-traits.h b/gcc/hash-traits.h index bef0bd4..f5d1270 100644 --- a/gcc/hash-traits.h +++ b/gcc/hash-traits.h @@ -85,41 +85,51 @@ typed_noop_remove <Type>::remove (Type &) { } +/* Base traits for integer type Type, providing just the hash and + comparison functionality. */ -/* Hasher for integer type Type in which Empty is a spare value that can be - used to mark empty slots. If Deleted != Empty then Deleted is another - spare value that can be used for deleted slots; if Deleted == Empty then - hash table entries cannot be deleted. */ - -template <typename Type, Type Empty, Type Deleted = Empty> -struct int_hash : typed_noop_remove <Type> +template <typename Type> +struct int_hash_base : typed_noop_remove <Type> { typedef Type value_type; typedef Type compare_type; static inline hashval_t hash (value_type); static inline bool equal (value_type existing, value_type candidate); - static inline void mark_deleted (Type &); - static const bool empty_zero_p = Empty == 0; - static inline void mark_empty (Type &); - static inline bool is_deleted (Type); - static inline bool is_empty (Type); }; -template <typename Type, Type Empty, Type Deleted> +template <typename Type> inline hashval_t -int_hash <Type, Empty, Deleted>::hash (value_type x) +int_hash_base <Type>::hash (value_type x) { return x; } -template <typename Type, Type Empty, Type Deleted> +template <typename Type> inline bool -int_hash <Type, Empty, Deleted>::equal (value_type x, value_type y) +int_hash_base <Type>::equal (value_type x, value_type y) { return x == y; } +/* Hasher for integer type Type in which Empty is a spare value that can be + used to mark empty slots. If Deleted != Empty then Deleted is another + spare value that can be used for deleted slots; if Deleted == Empty then + hash table entries cannot be deleted. */ + +template <typename Type, Type Empty, Type Deleted = Empty> +struct int_hash : int_hash_base <Type> +{ + typedef Type value_type; + typedef Type compare_type; + + static inline void mark_deleted (Type &); + static const bool empty_zero_p = Empty == 0; + static inline void mark_empty (Type &); + static inline bool is_deleted (Type); + static inline bool is_empty (Type); +}; + template <typename Type, Type Empty, Type Deleted> inline void int_hash <Type, Empty, Deleted>::mark_deleted (Type &x) @@ -398,6 +408,61 @@ pair_hash <T1, T2>::is_empty (const value_type &x) return T1::is_empty (x.first); } +/* Base traits for vectors, providing just the hash and comparison + functionality. Type gives the corresponding traits for the element + type. */ + +template <typename Type> +struct vec_hash_base +{ + typedef vec<typename Type::value_type> value_type; + typedef vec<typename Type::compare_type> compare_type; + + static inline hashval_t hash (value_type); + static inline bool equal (value_type, compare_type); +}; + +template <typename Type> +inline hashval_t +vec_hash_base <Type>::hash (value_type x) +{ + inchash::hash hstate; + hstate.add_int (x.length ()); + for (auto &value : x) + hstate.merge_hash (Type::hash (value)); + return hstate.end (); +} + +template <typename Type> +inline bool +vec_hash_base <Type>::equal (value_type x, compare_type y) +{ + if (x.length () != y.length ()) + return false; + for (unsigned int i = 0; i < x.length (); ++i) + if (!Type::equal (x[i], y[i])) + return false; + return true; +} + +/* Traits for vectors whose contents should be freed normally. */ + +template <typename Type> +struct vec_free_hash_base : vec_hash_base <Type> +{ + static void remove (typename vec_hash_base <Type>::value_type &); +}; + +template <typename Type> +void +vec_free_hash_base <Type> +::remove (typename vec_hash_base <Type>::value_type &x) +{ + for (auto &value : x) + Type::remove (x); + x.release (); +} + template <typename T> struct default_hash_traits : T {}; template <typename T> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index aa7c482..651d99e 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -368,6 +368,14 @@ expand_GOMP_SIMT_VF (internal_fn, gcall *) gcc_unreachable (); } +/* This should get expanded in omp_device_lower pass. */ + +static void +expand_GOMP_TARGET_REV (internal_fn, gcall *) +{ + gcc_unreachable (); +} + /* Lane index of the first SIMT lane that supplies a non-zero argument. This is a SIMT counterpart to GOMP_SIMD_LAST_LANE, used to represent the lane that executed the last iteration for handling OpenMP lastprivate. */ diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 7bf661c..f49b395 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -336,6 +336,7 @@ DEF_INTERNAL_INT_FN (FFS, ECF_CONST | ECF_NOTHROW, ffs, unary) DEF_INTERNAL_INT_FN (PARITY, ECF_CONST | ECF_NOTHROW, parity, unary) DEF_INTERNAL_INT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary) +DEF_INTERNAL_FN (GOMP_TARGET_REV, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_USE_SIMT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_SIMT_ENTER, ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_SIMT_ENTER_ALLOC, ECF_LEAF | ECF_NOTHROW, NULL) @@ -458,7 +459,8 @@ DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) /* __builtin_trap created from/for __builtin_unreachable. */ DEF_INTERNAL_FN (TRAP, ECF_CONST | ECF_LEAF | ECF_NORETURN - | ECF_NOTHROW | ECF_COLD, NULL) + | ECF_NOTHROW | ECF_COLD | ECF_LOOPING_CONST_OR_PURE, + NULL) #undef DEF_INTERNAL_INT_FN #undef DEF_INTERNAL_FLT_FN diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc index 39af9c1..350195d 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -430,6 +430,13 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, after reading back. */ in_other_partition = 1; } + else if (UNLIKELY (lto_stream_offload_p + && lookup_attribute ("omp target device_ancestor_host", + DECL_ATTRIBUTES (node->decl)))) + /* This symbol is only used as argument to IFN_GOMP_TARGET_REV; this IFN + is ignored on ACCEL_COMPILER. Thus, mark it as in_other_partition to silence + verify_node_partition diagnostic. */ + in_other_partition = 1; clone_of = node->clone_of; while (clone_of @@ -1140,10 +1147,15 @@ verify_node_partition (symtab_node *node) if (node->in_other_partition) { if (TREE_CODE (node->decl) == FUNCTION_DECL) - error_at (DECL_SOURCE_LOCATION (node->decl), - "function %qs has been referenced in offloaded code but" - " hasn%'t been marked to be included in the offloaded code", - node->name ()); + { + if (lookup_attribute ("omp target device_ancestor_host", + DECL_ATTRIBUTES (node->decl)) != NULL) + return; + error_at (DECL_SOURCE_LOCATION (node->decl), + "function %qs has been referenced in offloaded code but" + " hasn%'t been marked to be included in the offloaded code", + node->name ()); + } else if (VAR_P (node->decl)) error_at (DECL_SOURCE_LOCATION (node->decl), "variable %qs has been referenced in offloaded code but" diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc index 471f35c..1bc3f55 100644 --- a/gcc/lto-streamer-out.cc +++ b/gcc/lto-streamer-out.cc @@ -1553,6 +1553,9 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map, case OMP_CLAUSE_DEPEND: val = OMP_CLAUSE_DEPEND_KIND (t); break; + case OMP_CLAUSE_DOACROSS: + val = OMP_CLAUSE_DOACROSS_KIND (t); + break; case OMP_CLAUSE_MAP: val = OMP_CLAUSE_MAP_KIND (t); break; diff --git a/gcc/match.pd b/gcc/match.pd index 1bb936f..17318f52 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4804,7 +4804,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!HONOR_SIGNED_ZEROS (type)) @1)) (simplify - (cnd (cmp @0 zerop) integer_zerop (negate@1 @0)) + (cnd (cmp @0 zerop) zerop (negate@1 @0)) (if (!HONOR_SIGNED_ZEROS (type)) @1)) ) @@ -5300,7 +5300,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) if (cmp == LT_EXPR || cmp == GE_EXPR) tow = dconst0; else - real_inf (&tow); + tow = dconstinf; real_nextafter (&c2alt, fmt, &c2, &tow); real_convert (&c2alt, fmt, &c2alt); if (REAL_VALUE_ISINF (c2alt)) diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index 48fbd15..55c513d 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -3298,6 +3298,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, gimple_stmt_iterator gsi2 = *gsi; bool warned_step = false; + if (deps == NULL) + { + sorry_at (loc, "%<doacross(sink:omp_cur_iteration-1)%> not supported yet"); + return; + } for (i = 0; i < fd->ordered; i++) { tree step = NULL_TREE; @@ -3321,9 +3326,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, break; forward = tree_int_cst_sgn (step) != -1; } - if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) - warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier " - "waiting for lexically later iteration"); + if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) + warning_at (loc, 0, "%qs clause with %<sink%> modifier " + "waiting for lexically later iteration", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); break; } deps = TREE_CHAIN (deps); @@ -3377,13 +3384,13 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, tree co = fold_convert_loc (loc, itype, off); if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))) { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) co = fold_build1_loc (loc, NEGATE_EXPR, itype, co); a = fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (fd->loops[i].v), fd->loops[i].v, co); } - else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v), fd->loops[i].v, co); else @@ -3392,13 +3399,13 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, if (step) { tree t1, t2; - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, fd->loops[i].n1); else t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); else @@ -3420,14 +3427,14 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, } else if (fd->loops[i].cond_code == LT_EXPR) { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a, fd->loops[i].n1); else t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a, fd->loops[i].n2); } - else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + else if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a, fd->loops[i].n2); else @@ -3459,9 +3466,11 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, build_int_cst (itype, 0)); if (integer_zerop (t) && !warned_step) { - warning_at (loc, 0, "%<depend%> clause with %<sink%> modifier " + warning_at (loc, 0, "%qs clause with %<sink%> modifier " "refers to iteration never in the iteration " - "space"); + "space", + OMP_CLAUSE_DOACROSS_DEPEND (c) + ? "depend" : "doacross"); warned_step = true; } cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, @@ -3486,7 +3495,7 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, s)); else off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s); - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps)) + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) off = fold_build1_loc (loc, NEGATE_EXPR, itype, off); off = fold_convert_loc (loc, fd->iter_type, off); if (i <= fd->collapse - 1 && fd->collapse > 1) @@ -3559,13 +3568,13 @@ expand_omp_ordered_source_sink (struct omp_region *region, tree c; for (c = gimple_omp_ordered_clauses (ord_stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE) + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE) break; if (c) expand_omp_ordered_source (&gsi, fd, counts, loc); for (c = gimple_omp_ordered_clauses (ord_stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) expand_omp_ordered_sink (&gsi, fd, counts, c, loc); gsi_remove (&gsi, true); } @@ -9663,7 +9672,7 @@ expand_omp_target (struct omp_region *region) { basic_block entry_bb, exit_bb, new_bb; struct function *child_cfun; - tree child_fn, block, t; + tree child_fn, child_fn2, block, t, c; gimple_stmt_iterator gsi; gomp_target *entry_stmt; gimple *stmt; @@ -9700,10 +9709,16 @@ expand_omp_target (struct omp_region *region) gcc_unreachable (); } - child_fn = NULL_TREE; + tree clauses = gimple_omp_target_clauses (entry_stmt); + + bool is_ancestor = false; + child_fn = child_fn2 = NULL_TREE; child_cfun = NULL; if (offloaded) { + c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE); + if (ENABLE_OFFLOADING && c) + is_ancestor = OMP_CLAUSE_DEVICE_ANCESTOR (c); child_fn = gimple_omp_target_child_fn (entry_stmt); child_cfun = DECL_STRUCT_FUNCTION (child_fn); } @@ -9891,7 +9906,8 @@ expand_omp_target (struct omp_region *region) { if (in_lto_p) DECL_PRESERVE_P (child_fn) = 1; - vec_safe_push (offload_funcs, child_fn); + if (!is_ancestor) + vec_safe_push (offload_funcs, child_fn); } bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl) @@ -9930,11 +9946,88 @@ expand_omp_target (struct omp_region *region) } adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn); + + /* Handle the case that an inner ancestor:1 target is called by an outer + target region. */ + if (!is_ancestor) + cgraph_node::get (child_fn)->calls_declare_variant_alt + |= cgraph_node::get (cfun->decl)->calls_declare_variant_alt; + else /* Duplicate function to create empty nonhost variant. */ + { + /* Enable pass_omp_device_lower pass. */ + cgraph_node::get (cfun->decl)->calls_declare_variant_alt = 1; + cgraph_node *fn2_node; + child_fn2 = build_decl (DECL_SOURCE_LOCATION (child_fn), + FUNCTION_DECL, + clone_function_name (child_fn, "nohost"), + TREE_TYPE (child_fn)); + if (in_lto_p) + DECL_PRESERVE_P (child_fn2) = 1; + TREE_STATIC (child_fn2) = 1; + DECL_ARTIFICIAL (child_fn2) = 1; + DECL_IGNORED_P (child_fn2) = 0; + TREE_PUBLIC (child_fn2) = 0; + DECL_UNINLINABLE (child_fn2) = 1; + DECL_EXTERNAL (child_fn2) = 0; + DECL_CONTEXT (child_fn2) = NULL_TREE; + DECL_INITIAL (child_fn2) = make_node (BLOCK); + BLOCK_SUPERCONTEXT (DECL_INITIAL (child_fn2)) = child_fn2; + DECL_ATTRIBUTES (child_fn) + = remove_attribute ("omp target entrypoint", + DECL_ATTRIBUTES (child_fn)); + DECL_ATTRIBUTES (child_fn2) + = tree_cons (get_identifier ("omp target device_ancestor_nohost"), + NULL_TREE, copy_list (DECL_ATTRIBUTES (child_fn))); + DECL_ATTRIBUTES (child_fn) + = tree_cons (get_identifier ("omp target device_ancestor_host"), + NULL_TREE, DECL_ATTRIBUTES (child_fn)); + DECL_FUNCTION_SPECIFIC_OPTIMIZATION (child_fn2) + = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl); + DECL_FUNCTION_SPECIFIC_TARGET (child_fn2) + = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl); + DECL_FUNCTION_VERSIONED (child_fn2) + = DECL_FUNCTION_VERSIONED (current_function_decl); + + fn2_node = cgraph_node::get_create (child_fn2); + fn2_node->offloadable = 1; + fn2_node->force_output = 1; + node->offloadable = 0; + + t = build_decl (DECL_SOURCE_LOCATION (child_fn), + RESULT_DECL, NULL_TREE, void_type_node); + DECL_ARTIFICIAL (t) = 1; + DECL_IGNORED_P (t) = 1; + DECL_CONTEXT (t) = child_fn2; + DECL_RESULT (child_fn2) = t; + DECL_SAVED_TREE (child_fn2) = build1 (RETURN_EXPR, + void_type_node, NULL); + tree tmp = DECL_ARGUMENTS (child_fn); + t = build_decl (DECL_SOURCE_LOCATION (child_fn), PARM_DECL, + DECL_NAME (tmp), TREE_TYPE (tmp)); + DECL_ARTIFICIAL (t) = 1; + DECL_NAMELESS (t) = 1; + DECL_ARG_TYPE (t) = ptr_type_node; + DECL_CONTEXT (t) = current_function_decl; + TREE_USED (t) = 1; + TREE_READONLY (t) = 1; + DECL_ARGUMENTS (child_fn2) = t; + gcc_assert (TREE_CHAIN (tmp) == NULL_TREE); + + gimplify_function_tree (child_fn2); + cgraph_node::add_new_function (child_fn2, true); + + vec_safe_push (offload_funcs, child_fn2); + if (dump_file && !gimple_in_ssa_p (cfun)) + { + dump_function_header (dump_file, child_fn2, dump_flags); + dump_function_to_file (child_fn2, dump_file, dump_flags); + } + } } /* Emit a library call to launch the offloading region, or do data transfers. */ - tree t1, t2, t3, t4, depend, c, clauses; + tree t1, t2, t3, t4, depend; enum built_in_function start_ix; unsigned int flags_i = 0; @@ -9984,8 +10077,6 @@ expand_omp_target (struct omp_region *region) gcc_unreachable (); } - clauses = gimple_omp_target_clauses (entry_stmt); - tree device = NULL_TREE; location_t device_loc = UNKNOWN_LOCATION; tree goacc_flags = NULL_TREE; @@ -10017,7 +10108,8 @@ expand_omp_target (struct omp_region *region) need_device_adjustment = true; device_loc = OMP_CLAUSE_LOCATION (c); if (OMP_CLAUSE_DEVICE_ANCESTOR (c)) - sorry_at (device_loc, "%<ancestor%> not yet supported"); + device = build_int_cst (integer_type_node, + GOMP_DEVICE_HOST_FALLBACK); } else { @@ -10194,7 +10286,7 @@ expand_omp_target (struct omp_region *region) else args.quick_push (device); if (offloaded) - args.quick_push (build_fold_addr_expr (child_fn)); + args.quick_push (build_fold_addr_expr (child_fn2 ? child_fn2 : child_fn)); args.quick_push (t1); args.quick_push (t2); args.quick_push (t3); @@ -10316,6 +10408,14 @@ expand_omp_target (struct omp_region *region) /* Push terminal marker - zero. */ args.safe_push (oacc_launch_pack (0, NULL_TREE, 0)); + if (child_fn2) + { + g = gimple_build_call_internal (IFN_GOMP_TARGET_REV, 1, + build_fold_addr_expr (child_fn)); + gimple_set_location (g, gimple_location (entry_stmt)); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + } + g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args); gimple_set_location (g, gimple_location (entry_stmt)); gsi_insert_before (&gsi, g, GSI_SAME_STMT); @@ -10388,7 +10488,7 @@ expand_omp (struct omp_region *region) gomp_ordered *ord_stmt = as_a <gomp_ordered *> (last_stmt (region->entry)); if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) { /* We'll expand these when expanding corresponding worksharing region with ordered(n) clause. */ @@ -10518,7 +10618,7 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, else if (code == GIMPLE_OMP_ORDERED && omp_find_clause (gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) /* #pragma omp ordered depend is also just a stand-alone directive. */ region = NULL; @@ -10744,7 +10844,7 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region, fallthru = true; if (omp_find_clause (gimple_omp_ordered_clauses (as_a <gomp_ordered *> (last)), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) cur_region = cur_region->outer; break; diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 33792ad..0b4ec82 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -241,8 +241,13 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd, break; case OMP_CLAUSE_ORDERED: fd->have_ordered = true; - if (OMP_CLAUSE_ORDERED_EXPR (t)) - fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t)); + if (OMP_CLAUSE_ORDERED_DOACROSS (t)) + { + if (OMP_CLAUSE_ORDERED_EXPR (t)) + fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t)); + else + fd->ordered = -1; + } break; case OMP_CLAUSE_SCHEDULE: gcc_assert (!distribute && !taskloop); @@ -301,6 +306,9 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd, break; } + if (fd->ordered == -1) + fd->ordered = fd->collapse; + /* For order(reproducible:concurrent) schedule ({dynamic,guided,runtime}) we have either the option to expensively remember at runtime how we've distributed work from first loop and reuse that in following loops with diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index fdf34d6..b32336b 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -2101,6 +2101,11 @@ create_omp_child_function (omp_context *ctx, bool task_copy) else target_attr = NULL; } + if (target_attr + && is_gimple_omp_offloaded (ctx->stmt) + && lookup_attribute ("noclone", DECL_ATTRIBUTES (decl)) == NULL_TREE) + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("noclone"), + NULL_TREE, DECL_ATTRIBUTES (decl)); if (target_attr) DECL_ATTRIBUTES (decl) = tree_cons (get_identifier (target_attr), @@ -3631,14 +3636,13 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) break; case GIMPLE_OMP_TASK: for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c); error_at (OMP_CLAUSE_LOCATION (c), - "%<depend(%s)%> is only allowed in %<omp ordered%>", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + "%<%s(%s)%> is only allowed in %<omp ordered%>", + OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross", + kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); return false; } break; @@ -3646,43 +3650,30 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)); c; c = OMP_CLAUSE_CHAIN (c)) { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS) { - gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD); - continue; - } - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); - if (kind == OMP_CLAUSE_DEPEND_SOURCE - || kind == OMP_CLAUSE_DEPEND_SINK) - { - tree oclause; - /* Look for containing ordered(N) loop. */ - if (ctx == NULL - || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR - || (oclause - = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), - OMP_CLAUSE_ORDERED)) == NULL_TREE) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND) { error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause " - "must be closely nested inside an %<ordered%> " - "loop"); - return false; - } - else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<ordered%> construct with %<depend%> clause " - "must be closely nested inside a loop with " - "%<ordered%> clause with a parameter"); + "invalid depend kind in omp %<ordered%> %<depend%>"); return false; } + gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD); + continue; } - else + + tree oclause; + /* Look for containing ordered(N) loop. */ + if (ctx == NULL + || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR + || (oclause + = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), + OMP_CLAUSE_ORDERED)) == NULL_TREE) { error_at (OMP_CLAUSE_LOCATION (c), - "invalid depend kind in omp %<ordered%> %<depend%>"); + "%<ordered%> construct with %<depend%> clause " + "must be closely nested inside an %<ordered%> loop"); return false; } } @@ -3727,14 +3718,37 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) "a loop region with an %<ordered%> clause"); return false; } - if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE - && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE) + if (omp_find_clause (c, OMP_CLAUSE_DOACROSS) == NULL_TREE) { - error_at (gimple_location (stmt), - "%<ordered%> region without %<depend%> clause may " - "not be closely nested inside a loop region with " - "an %<ordered%> clause with a parameter"); - return false; + if (OMP_CLAUSE_ORDERED_DOACROSS (o)) + { + error_at (gimple_location (stmt), + "%<ordered%> construct without %<doacross%> or " + "%<depend%> clauses must not have the same " + "binding region as %<ordered%> construct with " + "those clauses"); + return false; + } + else if (OMP_CLAUSE_ORDERED_EXPR (o)) + { + tree co + = omp_find_clause (gimple_omp_for_clauses (ctx->stmt), + OMP_CLAUSE_COLLAPSE); + HOST_WIDE_INT + o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o)); + HOST_WIDE_INT c_n = 1; + if (co) + c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co)); + if (o_n != c_n) + { + error_at (gimple_location (stmt), + "%<ordered%> construct without %<doacross%> " + "or %<depend%> clauses binds to loop where " + "%<collapse%> argument %wd is different from " + "%<ordered%> argument %wd", c_n, o_n); + return false; + } + } } return true; case GIMPLE_OMP_TARGET: @@ -3788,14 +3802,12 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) break; case GIMPLE_OMP_TARGET: for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE - || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS) { - enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c); + enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c); error_at (OMP_CLAUSE_LOCATION (c), "%<depend(%s)%> is only allowed in %<omp ordered%>", - kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink"); + kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink"); return false; } if (is_gimple_omp_offloaded (stmt) @@ -4519,12 +4531,9 @@ omp_reduction_init_op (location_t loc, enum tree_code op, tree type) case MAX_EXPR: if (SCALAR_FLOAT_TYPE_P (type)) { - REAL_VALUE_TYPE max, min; + REAL_VALUE_TYPE min; if (HONOR_INFINITIES (type)) - { - real_inf (&max); - real_arithmetic (&min, NEGATE_EXPR, &max, NULL); - } + real_arithmetic (&min, NEGATE_EXPR, &dconstinf, NULL); else real_maxval (&min, 1, TYPE_MODE (type)); return build_real (type, min); @@ -4546,7 +4555,7 @@ omp_reduction_init_op (location_t loc, enum tree_code op, tree type) { REAL_VALUE_TYPE max; if (HONOR_INFINITIES (type)) - real_inf (&max); + max = dconstinf; else real_maxval (&max, 0, TYPE_MODE (type)); return build_real (type, max); @@ -9738,8 +9747,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt); tree c = gimple_omp_ordered_clauses (ord_stmt); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS + && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK) { /* Merge depend clauses from multiple adjacent #pragma omp ordered depend(sink:...) constructs @@ -9761,8 +9770,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt); c = gimple_omp_ordered_clauses (ord_stmt2); if (c == NULL_TREE - || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK) + || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS + || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK) break; while (*list_p) list_p = &OMP_CLAUSE_CHAIN (*list_p); @@ -9829,8 +9838,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, { bool remove = false; - gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND); - if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK) + gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS); + if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK) goto next_ordered_clause; tree vec; @@ -9981,7 +9990,7 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx) OMP_CLAUSE_THREADS); if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt), - OMP_CLAUSE_DEPEND)) + OMP_CLAUSE_DOACROSS)) { /* FIXME: This is needs to be moved to the expansion to verify various conditions only testable on cfg with dominators computed, and also @@ -12357,9 +12366,6 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq) case OMP_CLAUSE_DEPEND_INOUTSET: cnt[4]++; break; - case OMP_CLAUSE_DEPEND_SOURCE: - case OMP_CLAUSE_DEPEND_SINK: - /* FALLTHRU */ default: gcc_unreachable (); } diff --git a/gcc/omp-offload.cc b/gcc/omp-offload.cc index 3a89119..77be066 100644 --- a/gcc/omp-offload.cc +++ b/gcc/omp-offload.cc @@ -2627,6 +2627,47 @@ execute_omp_device_lower () tree type = lhs ? TREE_TYPE (lhs) : integer_type_node; switch (gimple_call_internal_fn (stmt)) { + case IFN_GOMP_TARGET_REV: + { +#ifndef ACCEL_COMPILER + gimple_stmt_iterator gsi2 = gsi; + gsi_next (&gsi2); + gcc_assert (!gsi_end_p (gsi2)); + gcc_assert (gimple_call_builtin_p (gsi_stmt (gsi2), + BUILT_IN_GOMP_TARGET)); + tree old_decl + = TREE_OPERAND (gimple_call_arg (gsi_stmt (gsi2), 1), 0); + tree new_decl = gimple_call_arg (gsi_stmt (gsi), 0); + gimple_call_set_arg (gsi_stmt (gsi2), 1, new_decl); + update_stmt (gsi_stmt (gsi2)); + new_decl = TREE_OPERAND (new_decl, 0); + unsigned i; + unsigned num_funcs = vec_safe_length (offload_funcs); + for (i = 0; i < num_funcs; i++) + { + if ((*offload_funcs)[i] == old_decl) + { + (*offload_funcs)[i] = new_decl; + break; + } + else if ((*offload_funcs)[i] == new_decl) + break; /* This can happen due to inlining. */ + } + gcc_assert (i < num_funcs); +#else + tree old_decl = TREE_OPERAND (gimple_call_arg (gsi_stmt (gsi), 0), + 0); +#endif + /* FIXME: Find a way to actually prevent outputting the empty-body + old_decl as debug symbol + function in the assembly file. */ + cgraph_node *node = cgraph_node::get (old_decl); + node->address_taken = false; + node->need_lto_streaming = false; + node->offloadable = false; + + unlink_stmt_vdef (stmt); + } + break; case IFN_GOMP_USE_SIMT: rhs = vf == 1 ? integer_zero_node : integer_one_node; break; @@ -2803,6 +2844,15 @@ pass_omp_target_link::execute (function *fun) { if (gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_GOMP_TARGET)) { + tree dev = gimple_call_arg (gsi_stmt (gsi), 0); + tree fn = gimple_call_arg (gsi_stmt (gsi), 1); + if (POINTER_TYPE_P (TREE_TYPE (fn))) + fn = TREE_OPERAND (fn, 0); + if (TREE_CODE (dev) == INTEGER_CST + && wi::to_wide (dev) == GOMP_DEVICE_HOST_FALLBACK + && lookup_attribute ("omp target device_ancestor_nohost", + DECL_ATTRIBUTES (fn)) != NULL_TREE) + continue; /* ancestor:1 */ /* Nullify the second argument of __builtin_GOMP_target_ext. */ gimple_call_set_arg (gsi_stmt (gsi), 1, null_pointer_node); update_stmt (gsi_stmt (gsi)); diff --git a/gcc/omp-simd-clone.cc b/gcc/omp-simd-clone.cc index 58bd68b..34cbee5 100644 --- a/gcc/omp-simd-clone.cc +++ b/gcc/omp-simd-clone.cc @@ -504,7 +504,10 @@ simd_clone_adjust_return_type (struct cgraph_node *node) veclen = node->simdclone->vecsize_int; else veclen = node->simdclone->vecsize_float; - veclen = exact_div (veclen, GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t))); + if (known_eq (veclen, 0U)) + veclen = node->simdclone->simdlen; + else + veclen = exact_div (veclen, GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t))); if (multiple_p (veclen, node->simdclone->simdlen)) veclen = node->simdclone->simdlen; if (POINTER_TYPE_P (t)) @@ -618,8 +621,12 @@ simd_clone_adjust_argument_types (struct cgraph_node *node) veclen = sc->vecsize_int; else veclen = sc->vecsize_float; - veclen = exact_div (veclen, - GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type))); + if (known_eq (veclen, 0U)) + veclen = sc->simdlen; + else + veclen + = exact_div (veclen, + GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type))); if (multiple_p (veclen, sc->simdlen)) veclen = sc->simdlen; adj.op = IPA_PARAM_OP_NEW; @@ -669,8 +676,11 @@ simd_clone_adjust_argument_types (struct cgraph_node *node) veclen = sc->vecsize_int; else veclen = sc->vecsize_float; - veclen = exact_div (veclen, - GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type))); + if (known_eq (veclen, 0U)) + veclen = sc->simdlen; + else + veclen = exact_div (veclen, + GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type))); if (multiple_p (veclen, sc->simdlen)) veclen = sc->simdlen; if (sc->mask_mode != VOIDmode) diff --git a/gcc/optabs.def b/gcc/optabs.def index 801310e..a6db234 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -313,6 +313,7 @@ OPTAB_D (fmod_optab, "fmod$a3") OPTAB_D (hypot_optab, "hypot$a3") OPTAB_D (ilogb_optab, "ilogb$a2") OPTAB_D (isinf_optab, "isinf$a2") +OPTAB_D (issignaling_optab, "issignaling$a2") OPTAB_D (ldexp_optab, "ldexp$a3") OPTAB_D (log10_optab, "log10$a2") OPTAB_D (log1p_optab, "log1p$a2") diff --git a/gcc/opts.cc b/gcc/opts.cc index 54e57f3..e058aaf 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -53,7 +53,7 @@ const char *const debug_type_names[] = static uint32_t debug_type_masks[] = { - NO_DEBUG, DBX_DEBUG, DWARF2_DEBUG, XCOFF_DEBUG, VMS_DEBUG, + NO_DEBUG, DWARF2_DEBUG, VMS_DEBUG, CTF_DEBUG, BTF_DEBUG }; @@ -3145,22 +3145,10 @@ common_handle_option (struct gcc_options *opts, set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc); break; - case OPT_gstabs: - case OPT_gstabs_: - set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set, - loc); - break; - case OPT_gvms: set_debug_level (VMS_DEBUG, false, arg, opts, opts_set, loc); break; - case OPT_gxcoff: - case OPT_gxcoff_: - set_debug_level (XCOFF_DEBUG, code == OPT_gxcoff_, arg, opts, opts_set, - loc); - break; - case OPT_gz: case OPT_gz_: /* Handled completely via specs. */ @@ -3363,8 +3351,6 @@ set_debug_level (uint32_t dinfo, int extended, const char *arg, struct gcc_options *opts, struct gcc_options *opts_set, location_t loc) { - opts->x_use_gnu_debug_info_extensions = extended; - if (dinfo == NO_DEBUG) { if (opts->x_write_symbols == NO_DEBUG) @@ -3378,8 +3364,6 @@ set_debug_level (uint32_t dinfo, int extended, const char *arg, opts->x_write_symbols |= DWARF2_DEBUG; else opts->x_write_symbols = DWARF2_DEBUG; -#elif defined DBX_DEBUGGING_INFO - opts->x_write_symbols = DBX_DEBUG; #endif } @@ -527,4 +527,40 @@ extern char *gen_producer_string (const char *language_string, #define OPTION_SET_P(OPTION) global_options_set.x_ ## OPTION +/* Find all the switches given to us + and make a vector describing them. + The elements of the vector are strings, one per switch given. + If a switch uses following arguments, then the `part1' field + is the switch itself and the `args' field + is a null-terminated vector containing the following arguments. + Bits in the `live_cond' field are: + SWITCH_LIVE to indicate this switch is true in a conditional spec. + SWITCH_FALSE to indicate this switch is overridden by a later switch. + SWITCH_IGNORE to indicate this switch should be ignored (used in %<S). + SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored. + SWITCH_KEEP_FOR_GCC to indicate that this switch, otherwise ignored, + should be included in COLLECT_GCC_OPTIONS. + in all do_spec calls afterwards. Used for %<S from self specs. + The `known' field describes whether this is an internal switch. + The `validated' field describes whether any spec has looked at this switch; + if it remains false at the end of the run, the switch must be meaningless. + The `ordering' field is used to temporarily mark switches that have to be + kept in a specific order. */ + +#define SWITCH_LIVE (1 << 0) +#define SWITCH_FALSE (1 << 1) +#define SWITCH_IGNORE (1 << 2) +#define SWITCH_IGNORE_PERMANENTLY (1 << 3) +#define SWITCH_KEEP_FOR_GCC (1 << 4) + +struct switchstr +{ + const char *part1; + const char **args; + unsigned int live_cond; + bool known; + bool validated; + bool ordering; +}; + #endif diff --git a/gcc/params.opt b/gcc/params.opt index 201b5c9..3001566 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -1137,6 +1137,10 @@ Whether to use canonical types. Common Joined UInteger Var(param_vect_epilogues_nomask) Init(1) IntegerRange(0, 1) Param Optimization Enable loop epilogue vectorization using smaller vector size. +-param=vect-max-layout-candidates= +Common Joined UInteger Var(param_vect_max_layout_candidates) Init(32) Param Optimization +Maximum number of possible vector layouts (such as permutations) to consider when optimizing to-be-vectorized code. + -param=vect-max-peeling-for-alignment= Common Joined UInteger Var(param_vect_max_peeling_for_alignment) Init(-1) IntegerRange(0, 64) Param Optimization Maximum number of loop peels to enhance alignment of data references in a loop. diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog index 76a8e17..eeb2b8e 100644 --- a/gcc/po/ChangeLog +++ b/gcc/po/ChangeLog @@ -1,3 +1,7 @@ +2022-08-30 Joseph Myers <joseph@codesourcery.com> + + * sv.po: Update. + 2022-08-23 Joseph Myers <joseph@codesourcery.com> * be.po, da.po, de.po, el.po, es.po, fi.po, fr.po, hr.po, id.po, diff --git a/gcc/po/sv.po b/gcc/po/sv.po index 94781b4..d15c134 100644 --- a/gcc/po/sv.po +++ b/gcc/po/sv.po @@ -1,4 +1,4 @@ -# Swedish messages for Sc's. +# Swedish messages for gcc. # Copyright © 2000, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Free Software Foundation, Inc. # This file is distributed under the same license as the gcc package. # Dennis Björklund <db@zigo.dhs.org>, 2000, 2001, 2002. @@ -26,10 +26,10 @@ # thunk snutt msgid "" msgstr "" -"Project-Id-Version: gcc 12.1.0\n" +"Project-Id-Version: gcc 12.2.0\n" "Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n" "POT-Creation-Date: 2022-08-17 22:17+0000\n" -"PO-Revision-Date: 2022-06-09 23:09+0200\n" +"PO-Revision-Date: 2022-08-26 22:47+0200\n" "Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -58837,10 +58837,9 @@ msgid "redeclared here as %q#D" msgstr "omdeklarerad här som %q#D" #: cp/pt.cc:6321 -#, fuzzy, gcc-internal-format -#| msgid "declared here" +#, gcc-internal-format msgid "redeclared here" -msgstr "deklarerad här" +msgstr "omdeklarerad här" #: cp/pt.cc:6332 #, gcc-internal-format @@ -62203,10 +62202,9 @@ msgid "toHash() must be declared as extern (D) size_t toHash() const nothrow @sa msgstr "toHash() mÃ¥ste deklareras som extern (D) size_t toHash() const nothrow @safe, inte %s" #: d/typeinfo.cc:1415 -#, fuzzy, gcc-internal-format -#| msgid "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>" +#, gcc-internal-format msgid "expression %qs requires %<object.TypeInfo%> and cannot be used with %<-fno-rtti%>" -msgstr "%<object.TypeInfo%> kan inte användas med %<-fno-rtti%>" +msgstr "uttrycket %qs kräver %<object.TypeInfo%> och kan inte användas med %<-fno-rtti%>" #: d/typeinfo.cc:1419 #, gcc-internal-format @@ -64853,10 +64851,9 @@ msgid "BIND(C) statement at %C" msgstr "BIND(C)-sats vid %C" #: fortran/decl.cc:6268 -#, fuzzy, gcc-internal-format, gfc-internal-format -#| msgid "CLASS variable %qs at %L cannot have the PARAMETER attribute" +#, gcc-internal-format, gfc-internal-format msgid "CLASS entity at %C cannot have the PARAMETER attribute" -msgstr "CLASS-variabeln %qs vid %L fÃ¥r inte ha attributet PARAMETER" +msgstr "CLASS-enheten vid %C fÃ¥r inte ha attributet PARAMETER" #: fortran/decl.cc:6300 #, gcc-internal-format, gfc-internal-format diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index ad2fae5..7301e5a0 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -150,6 +150,26 @@ range_operator_float::op1_op2_relation (const irange &lhs ATTRIBUTE_UNUSED) cons return VREL_VARYING; } +// Set R to [NAN, NAN]. + +static inline void +frange_set_nan (frange &r, tree type) +{ + REAL_VALUE_TYPE rv; + bool res = real_nan (&rv, "", 1, TYPE_MODE (type)); + if (flag_checking) + gcc_assert (res); + r.set (type, rv, rv); +} + +// Return TRUE if OP1 is known to be free of NANs. + +static inline bool +finite_operand_p (const frange &op1) +{ + return flag_finite_math_only || op1.get_nan ().no_p (); +} + // Return TRUE if OP1 and OP2 are known to be free of NANs. static inline bool @@ -178,22 +198,75 @@ frelop_early_resolve (irange &r, tree type, && relop_early_resolve (r, type, op1, op2, rel, my_rel)); } -// Default implementation of fold_range for relational operators. -// This amounts to passing on any known relations from the oracle, iff -// we know the operands are not NAN or -ffinite-math-only holds. +// Crop R to [-INF, MAX] where MAX is the maximum representable number +// for TYPE. -static inline bool -default_frelop_fold_range (irange &r, tree type, - const frange &op1, const frange &op2, - relation_kind rel, relation_kind my_rel) +static inline void +frange_drop_inf (frange &r, tree type) { - if (frelop_early_resolve (r, type, op1, op2, rel, my_rel)) - return true; + // FIXME: build_real() bails on decimal float modes when called with + // a max representable endpoint. + if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))) + return; + + REAL_VALUE_TYPE max; + real_max_representable (&max, type); + frange tmp (type, r.lower_bound (), max); + r.intersect (tmp); +} - r.set_varying (type); - return true; +// Crop R to [MIN, +INF] where MIN is the minimum representable number +// for TYPE. + +static inline void +frange_drop_ninf (frange &r, tree type) +{ + // FIXME: build_real() bails on decimal float modes when called with + // a max representable endpoint. + if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))) + return; + + REAL_VALUE_TYPE min; + real_min_representable (&min, type); + frange tmp (type, min, r.upper_bound ()); + r.intersect (tmp); +} + +// (X <= VAL) produces the range of [-INF, VAL]. + +static void +build_le (frange &r, tree type, const REAL_VALUE_TYPE &val) +{ + r.set (type, dconstninf, val); +} + +// (X < VAL) produces the range of [-INF, VAL). + +static void +build_lt (frange &r, tree type, const REAL_VALUE_TYPE &val) +{ + // Hijack LE because we only support closed intervals. + build_le (r, type, val); +} + +// (X >= VAL) produces the range of [VAL, +INF]. + +static void +build_ge (frange &r, tree type, const REAL_VALUE_TYPE &val) +{ + r.set (type, val, dconstinf); +} + +// (X > VAL) produces the range of (VAL, +INF]. + +static void +build_gt (frange &r, tree type, const REAL_VALUE_TYPE &val) +{ + // Hijack GE because we only support closed intervals. + build_ge (r, type, val); } + class foperator_identity : public range_operator_float { using range_operator_float::fold_range; @@ -224,10 +297,7 @@ class foperator_equal : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_EQ); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return equal_op1_op2_relation (lhs); @@ -244,6 +314,39 @@ class foperator_equal : public range_operator_float } fop_equal; bool +foperator_equal::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_EQ)) + return true; + + // We can be sure the values are always equal or not if both ranges + // consist of a single value, and then compare them. + if (op1.singleton_p () && op2.singleton_p ()) + { + if (op1 == op2) + r = range_true (type); + else + r = range_false (type); + } + else if (finite_operands_p (op1, op2)) + { + // If ranges do not intersect, we know the range is not equal, + // otherwise we don't know anything for sure. + frange tmp = op1; + tmp.intersect (op2); + if (tmp.undefined_p ()) + r = range_false (type); + else + r = range_true_and_false (type); + } + else + r = range_true_and_false (type); + return true; +} + +bool foperator_equal::op1_range (frange &r, tree type, const irange &lhs, const frange &op2 ATTRIBUTE_UNUSED, @@ -254,6 +357,9 @@ foperator_equal::op1_range (frange &r, tree type, case BRS_TRUE: // If it's true, the result is the same as OP2. r = op2; + // Make sure we don't copy the sign bit if we may have a zero. + if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type))) + r.set_signbit (fp_prop::VARYING); // The TRUE side of op1 == op2 implies op1 is !NAN. r.set_nan (fp_prop::NO); break; @@ -262,7 +368,15 @@ foperator_equal::op1_range (frange &r, tree type, r.set_varying (type); // The FALSE side of op1 == op1 implies op1 is a NAN. if (rel == VREL_EQ) - r.set_nan (fp_prop::YES); + frange_set_nan (r, type); + // If the result is false, the only time we know anything is + // if OP2 is a constant. + else if (op2.singleton_p () + || (finite_operand_p (op2) && op2.zero_p ())) + { + REAL_VALUE_TYPE tmp = op2.lower_bound (); + r.set (type, tmp, tmp, VR_ANTI_RANGE); + } break; default: @@ -278,10 +392,7 @@ class foperator_not_equal : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_NE); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return not_equal_op1_op2_relation (lhs); @@ -292,6 +403,39 @@ class foperator_not_equal : public range_operator_float } fop_not_equal; bool +foperator_not_equal::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_NE)) + return true; + + // We can be sure the values are always equal or not if both ranges + // consist of a single value, and then compare them. + if (op1.singleton_p () && op2.singleton_p ()) + { + if (op1 != op2) + r = range_true (type); + else + r = range_false (type); + } + else if (finite_operands_p (op1, op2)) + { + // If ranges do not intersect, we know the range is not equal, + // otherwise we don't know anything for sure. + frange tmp = op1; + tmp.intersect (op2); + if (tmp.undefined_p ()) + r = range_true (type); + else + r = range_true_and_false (type); + } + else + r = range_true_and_false (type); + return true; +} + +bool foperator_not_equal::op1_range (frange &r, tree type, const irange &lhs, const frange &op2 ATTRIBUTE_UNUSED, @@ -300,11 +444,26 @@ foperator_not_equal::op1_range (frange &r, tree type, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); + // If the result is true, the only time we know anything is if + // OP2 is a constant. + if (op2.singleton_p ()) + { + // This is correct even if op1 is NAN, because the following + // range would be ~[tmp, tmp] with the NAN property set to + // maybe (VARYING). + REAL_VALUE_TYPE tmp = op2.lower_bound (); + r.set (type, tmp, tmp, VR_ANTI_RANGE); + } + else + r.set_varying (type); break; case BRS_FALSE: - r.set_varying (type); + // If it's false, the result is the same as OP2. + r = op2; + // Make sure we don't copy the sign bit if we may have a zero. + if (HONOR_SIGNED_ZEROS (type) && r.contains_p (build_zero_cst (type))) + r.set_signbit (fp_prop::VARYING); // The FALSE side of op1 != op2 implies op1 is !NAN. r.set_nan (fp_prop::NO); break; @@ -323,10 +482,7 @@ class foperator_lt : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_LT); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return lt_op1_op2_relation (lhs); @@ -340,6 +496,31 @@ class foperator_lt : public range_operator_float } fop_lt; bool +foperator_lt::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LT)) + return true; + + if (finite_operands_p (op1, op2)) + { + if (real_less (&op1.upper_bound (), &op2.lower_bound ())) + r = range_true (type); + else if (finite_operands_p (op1, op2) + && !real_less (&op1.lower_bound (), &op2.upper_bound ())) + r = range_false (type); + else + r = range_true_and_false (type); + } + else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ()) + r = range_false (type); + else + r = range_true_and_false (type); + return true; +} + +bool foperator_lt::op1_range (frange &r, tree type, const irange &lhs, @@ -349,14 +530,14 @@ foperator_lt::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 < op2 implies op1 is !NAN and !INF. + build_lt (r, type, op2.upper_bound ()); r.set_nan (fp_prop::NO); - r.set_inf (fp_prop::NO); + // x < y implies x is not +INF. + frange_drop_inf (r, type); break; case BRS_FALSE: - r.set_varying (type); + build_ge (r, type, op2.lower_bound ()); break; default: @@ -375,14 +556,14 @@ foperator_lt::op2_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 < op2 implies op2 is !NAN and !NINF. + build_gt (r, type, op1.lower_bound ()); r.set_nan (fp_prop::NO); - r.set_ninf (fp_prop::NO); + // x < y implies y is not -INF. + frange_drop_ninf (r, type); break; case BRS_FALSE: - r.set_varying (type); + build_le (r, type, op1.upper_bound ()); break; default: @@ -399,10 +580,7 @@ class foperator_le : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_LE); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return le_op1_op2_relation (lhs); @@ -412,29 +590,74 @@ class foperator_le : public range_operator_float relation_kind rel) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel) const final override - { - return op1_range (r, type, lhs, op1, rel); - } + relation_kind rel) const final override; } fop_le; bool +foperator_le::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_LE)) + return true; + + if (finite_operands_p (op1, op2)) + { + if (real_compare (LE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + r = range_true (type); + else if (finite_operands_p (op1, op2) + && !real_compare (LE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + r = range_false (type); + else + r = range_true_and_false (type); + } + else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ()) + r = range_false (type); + else + r = range_true_and_false (type); + return true; +} + +bool foperator_le::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 <= op2 implies op1 is !NAN. + build_le (r, type, op2.upper_bound ()); r.set_nan (fp_prop::NO); break; case BRS_FALSE: - r.set_varying (type); + build_gt (r, type, op2.lower_bound ()); + break; + + default: + break; + } + return true; +} + +bool +foperator_le::op2_range (frange &r, + tree type, + const irange &lhs, + const frange &op1, + relation_kind) const +{ + switch (get_bool_state (r, lhs, type)) + { + case BRS_TRUE: + build_ge (r, type, op1.lower_bound ()); + r.set_nan (fp_prop::NO); + break; + + case BRS_FALSE: + build_lt (r, type, op1.upper_bound ()); break; default: @@ -451,10 +674,7 @@ class foperator_gt : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_GT); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return gt_op1_op2_relation (lhs); @@ -468,6 +688,31 @@ class foperator_gt : public range_operator_float } fop_gt; bool +foperator_gt::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GT)) + return true; + + if (finite_operands_p (op1, op2)) + { + if (real_compare (GT_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + r = range_true (type); + else if (finite_operands_p (op1, op2) + && !real_compare (GT_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + r = range_false (type); + else + r = range_true_and_false (type); + } + else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ()) + r = range_false (type); + else + r = range_true_and_false (type); + return true; +} + +bool foperator_gt::op1_range (frange &r, tree type, const irange &lhs, @@ -477,14 +722,14 @@ foperator_gt::op1_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 > op2 implies op1 is !NAN and !NINF. + build_gt (r, type, op2.lower_bound ()); r.set_nan (fp_prop::NO); - r.set_ninf (fp_prop::NO); + // x > y implies x is not -INF. + frange_drop_ninf (r, type); break; case BRS_FALSE: - r.set_varying (type); + build_le (r, type, op2.upper_bound ()); break; default: @@ -503,14 +748,14 @@ foperator_gt::op2_range (frange &r, switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 > op2 implies op2 is !NAN and !INF. + build_lt (r, type, op1.upper_bound ()); r.set_nan (fp_prop::NO); - r.set_inf (fp_prop::NO); + // x > y implies y is not +INF. + frange_drop_inf (r, type); break; case BRS_FALSE: - r.set_varying (type); + build_ge (r, type, op1.lower_bound ()); break; default: @@ -527,10 +772,7 @@ class foperator_ge : public range_operator_float bool fold_range (irange &r, tree type, const frange &op1, const frange &op2, - relation_kind rel) const final override - { - return default_frelop_fold_range (r, type, op1, op2, rel, VREL_GE); - } + relation_kind rel) const final override; relation_kind op1_op2_relation (const irange &lhs) const final override { return ge_op1_op2_relation (lhs); @@ -540,29 +782,73 @@ class foperator_ge : public range_operator_float relation_kind rel) const final override; bool op2_range (frange &r, tree type, const irange &lhs, const frange &op1, - relation_kind rel) const final override - { - return op1_range (r, type, lhs, op1, rel); - } + relation_kind rel) const final override; } fop_ge; bool +foperator_ge::fold_range (irange &r, tree type, + const frange &op1, const frange &op2, + relation_kind rel) const +{ + if (frelop_early_resolve (r, type, op1, op2, rel, VREL_GE)) + return true; + + if (finite_operands_p (op1, op2)) + { + if (real_compare (GE_EXPR, &op1.lower_bound (), &op2.upper_bound ())) + r = range_true (type); + else if (finite_operands_p (op1, op2) + && !real_compare (GE_EXPR, &op1.upper_bound (), &op2.lower_bound ())) + r = range_false (type); + else + r = range_true_and_false (type); + } + else if (op1.get_nan ().yes_p () || op2.get_nan ().yes_p ()) + r = range_false (type); + else + r = range_true_and_false (type); + return true; +} + +bool foperator_ge::op1_range (frange &r, tree type, const irange &lhs, - const frange &op2 ATTRIBUTE_UNUSED, + const frange &op2, relation_kind) const { switch (get_bool_state (r, lhs, type)) { case BRS_TRUE: - r.set_varying (type); - // The TRUE side of op1 >= op2 implies op1 is !NAN. + build_ge (r, type, op2.lower_bound ()); r.set_nan (fp_prop::NO); break; case BRS_FALSE: - r.set_varying (type); + build_lt (r, type, op2.upper_bound ()); + break; + + default: + break; + } + return true; +} + +bool +foperator_ge::op2_range (frange &r, tree type, + const irange &lhs, + const frange &op1, + relation_kind) const +{ + switch (get_bool_state (r, lhs, type)) + { + case BRS_FALSE: + build_gt (r, type, op1.lower_bound ()); + break; + + case BRS_TRUE: + build_le (r, type, op1.upper_bound ()); + r.set_nan (fp_prop::NO); break; default: @@ -623,7 +909,7 @@ foperator_unordered::op1_range (frange &r, tree type, // Since at least one operand must be NAN, if one of them is // not, the other must be. if (op2.get_nan ().no_p ()) - r.set_nan (fp_prop::YES); + frange_set_nan (r, type); break; case BRS_FALSE: diff --git a/gcc/real.cc b/gcc/real.cc index 4e63b14..73bbac6 100644 --- a/gcc/real.cc +++ b/gcc/real.cc @@ -1234,6 +1234,14 @@ real_isinf (const REAL_VALUE_TYPE *r) return (r->cl == rvc_inf); } +/* Determine whether a floating-point value X is infinite with SIGN. */ + +bool +real_isinf (const REAL_VALUE_TYPE *r, bool sign) +{ + return real_isinf (r) && r->sign == sign; +} + /* Determine whether a floating-point value X is a NaN. */ bool @@ -1264,6 +1272,22 @@ real_isneg (const REAL_VALUE_TYPE *r) return r->sign; } +/* Determine whether a floating-point value X is plus or minus zero. */ + +bool +real_iszero (const REAL_VALUE_TYPE *r) +{ + return r->cl == rvc_zero; +} + +/* Determine whether a floating-point value X is zero with SIGN. */ + +bool +real_iszero (const REAL_VALUE_TYPE *r, bool sign) +{ + return real_iszero (r) && r->sign == sign; +} + /* Determine whether a floating-point value X is minus zero. */ bool @@ -2484,12 +2508,12 @@ dconst_sqrt2_ptr (void) return &value; } -/* Fills R with +Inf. */ +/* Fills R with Inf with SIGN. */ void -real_inf (REAL_VALUE_TYPE *r) +real_inf (REAL_VALUE_TYPE *r, bool sign) { - get_inf (r, 0); + get_inf (r, sign); } /* Fills R with a NaN whose significand is described by STR. If QUIET, @@ -2930,7 +2954,7 @@ encode_ieee_single (const struct real_format *fmt, long *buf, { unsigned long image, sig, exp; unsigned long sign = r->sign; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); image = sign << 31; sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; @@ -3151,7 +3175,7 @@ encode_ieee_double (const struct real_format *fmt, long *buf, { unsigned long image_lo, image_hi, sig_lo, sig_hi, exp; unsigned long sign = r->sign; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); image_hi = sign << 31; image_lo = 0; @@ -3409,7 +3433,7 @@ encode_ieee_extended (const struct real_format *fmt, long *buf, const REAL_VALUE_TYPE *r) { unsigned long image_hi, sig_hi, sig_lo; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); image_hi = r->sign << 15; sig_hi = sig_lo = 0; @@ -3940,7 +3964,7 @@ encode_ieee_quad (const struct real_format *fmt, long *buf, { unsigned long image3, image2, image1, image0, exp; unsigned long sign = r->sign; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); REAL_VALUE_TYPE u; image3 = sign << 31; @@ -4697,7 +4721,7 @@ encode_ieee_half (const struct real_format *fmt, long *buf, { unsigned long image, sig, exp; unsigned long sign = r->sign; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); image = sign << 15; sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 11)) & 0x3ff; @@ -4811,7 +4835,7 @@ encode_arm_bfloat_half (const struct real_format *fmt, long *buf, { unsigned long image, sig, exp; unsigned long sign = r->sign; - bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + bool denormal = real_isdenormal (r); image = sign << 15; sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 8)) & 0x7f; @@ -277,12 +277,22 @@ extern bool real_compare (int, const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *) /* Determine whether a floating-point value X is infinite. */ extern bool real_isinf (const REAL_VALUE_TYPE *); +/* Determine whether a floating-point value X is infinite with SIGN. */ +extern bool real_isinf (const REAL_VALUE_TYPE *, bool sign); + /* Determine whether a floating-point value X is a NaN. */ extern bool real_isnan (const REAL_VALUE_TYPE *); /* Determine whether a floating-point value X is a signaling NaN. */ extern bool real_issignaling_nan (const REAL_VALUE_TYPE *); +/* Determine whether a floating-point value X is a denormal. */ +inline bool +real_isdenormal (const REAL_VALUE_TYPE *r) +{ + return (r->sig[SIGSZ-1] & SIG_MSB) == 0; +} + /* Determine whether a floating-point value X is finite. */ extern bool real_isfinite (const REAL_VALUE_TYPE *); @@ -292,6 +302,12 @@ extern bool real_isneg (const REAL_VALUE_TYPE *); /* Determine whether a floating-point value X is minus zero. */ extern bool real_isnegzero (const REAL_VALUE_TYPE *); +/* Determine whether a floating-point value X is plus or minus zero. */ +extern bool real_iszero (const REAL_VALUE_TYPE *); + +/* Determine whether a floating-point value X is zero with SIGN. */ +extern bool real_iszero (const REAL_VALUE_TYPE *, bool sign); + /* Test relationships between reals. */ extern bool real_identical (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); extern bool real_equal (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); @@ -331,7 +347,7 @@ extern long real_to_target (long *, const REAL_VALUE_TYPE *, format_helper); extern void real_from_target (REAL_VALUE_TYPE *, const long *, format_helper); -extern void real_inf (REAL_VALUE_TYPE *); +extern void real_inf (REAL_VALUE_TYPE *, bool sign = false); extern bool real_nan (REAL_VALUE_TYPE *, const char *, int, format_helper); @@ -453,6 +469,8 @@ extern REAL_VALUE_TYPE dconst1; extern REAL_VALUE_TYPE dconst2; extern REAL_VALUE_TYPE dconstm1; extern REAL_VALUE_TYPE dconsthalf; +extern REAL_VALUE_TYPE dconstinf; +extern REAL_VALUE_TYPE dconstninf; #define dconst_e() (*dconst_e_ptr ()) #define dconst_third() (*dconst_third_ptr ()) diff --git a/gcc/realmpfr.cc b/gcc/realmpfr.cc index 54d097f..f7f0963 100644 --- a/gcc/realmpfr.cc +++ b/gcc/realmpfr.cc @@ -68,7 +68,7 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format, /* Take care of Infinity and NaN. */ if (mpfr_inf_p (m)) { - real_inf (r); + *r = dconstinf; if (mpfr_sgn (m) < 0) *r = real_value_negate (r); return; diff --git a/gcc/spellcheck.h b/gcc/spellcheck.h index 3706de3..1b76a54 100644 --- a/gcc/spellcheck.h +++ b/gcc/spellcheck.h @@ -95,7 +95,8 @@ class best_match : m_goal (goal_traits::get_string (goal)), m_goal_len (goal_traits::get_length (goal)), m_best_candidate (NULL), - m_best_distance (best_distance_so_far) + m_best_distance (best_distance_so_far), + m_best_candidate_len (0) {} /* Compare the edit distance between CANDIDATE and m_goal, diff --git a/gcc/stab.def b/gcc/stab.def deleted file mode 100644 index e5af19b..0000000 --- a/gcc/stab.def +++ /dev/null @@ -1,239 +0,0 @@ -/* Table of DBX symbol codes for the GNU system. - Copyright (C) 1988-2022 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version. - - The GNU C 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING3. If - not see <http://www.gnu.org/licenses/>. */ - -/* This contains contribution from Cygnus Support. */ - -/* Global variable. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_GSYM, 0x20, "GSYM") - -/* Function name for BSD Fortran. Only the name is significant. - To find the address, look in the corresponding external symbol. */ -__define_stab (N_FNAME, 0x22, "FNAME") - -/* Function name or text-segment variable for C. Value is its address. - Desc is supposedly starting line number, but GCC doesn't set it - and DBX seems not to miss it. */ -__define_stab (N_FUN, 0x24, "FUN") - -/* Data-segment variable with internal linkage. Value is its address. - "Static Sym". */ -__define_stab (N_STSYM, 0x26, "STSYM") - -/* BSS-segment variable with internal linkage. Value is its address. */ -__define_stab (N_LCSYM, 0x28, "LCSYM") - -/* Begin function marker. */ -__define_stab (N_BNSYM, 0x2e, "BNSYM") - -/* End function marker. */ -__define_stab (N_ENSYM, 0x4e, "ENSYM") - -/* Name of main routine. Only the name is significant. - This is not used in C. */ -__define_stab (N_MAIN, 0x2a, "MAIN") - -/* Global symbol in Pascal. - Supposedly the value is its line number; I'm skeptical. */ -__define_stab (N_PC, 0x30, "PC") - -/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ -__define_stab (N_NSYMS, 0x32, "NSYMS") - -/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ -__define_stab (N_NOMAP, 0x34, "NOMAP") - -/* New stab from Solaris. I don't know what it means, but it - don't seem to contain useful information. */ -__define_stab (N_OBJ, 0x38, "OBJ") - -/* New stab from Solaris. I don't know what it means, but it - don't seem to contain useful information. Possibly related to the - optimization flags used in this module. */ -__define_stab (N_OPT, 0x3c, "OPT") - -/* Register variable. Value is number of register. */ -__define_stab (N_RSYM, 0x40, "RSYM") - -/* Modula-2 compilation unit. Can someone say what info it contains? */ -__define_stab (N_M2C, 0x42, "M2C") - -/* Line number in text segment. Desc is the line number; - value is corresponding address. */ -__define_stab (N_SLINE, 0x44, "SLINE") - -/* Similar, for data segment. */ -__define_stab (N_DSLINE, 0x46, "DSLINE") - -/* Similar, for bss segment. */ -__define_stab (N_BSLINE, 0x48, "BSLINE") - -/* Sun's source-code browser stabs. ?? Don't know what the fields are. - Supposedly the field is "path to associated .cb file". THIS VALUE - OVERLAPS WITH N_BSLINE! */ -__define_stab (N_BROWS, 0x48, "BROWS") - -/* GNU Modula-2 definition module dependency. Value is the modification time - of the definition file. Other is nonzero if it is imported with the - GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there - are enough empty fields? */ -__define_stab(N_DEFD, 0x4a, "DEFD") - -/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 - and one is for C++. Still,... */ -/* GNU C++ exception variable. Name is variable name. */ -__define_stab (N_EHDECL, 0x50, "EHDECL") -/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ -__define_stab (N_MOD2, 0x50, "MOD2") - -/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if - this entry is immediately followed by a CAUGHT stab saying what exception - was caught. Multiple CAUGHT stabs means that multiple exceptions - can be caught here. If Desc is 0, it means all exceptions are caught - here. */ -__define_stab (N_CATCH, 0x54, "CATCH") - -/* Structure or union element. Value is offset in the structure. */ -__define_stab (N_SSYM, 0x60, "SSYM") - -/* Name of main source file. - Value is starting text address of the compilation. */ -__define_stab (N_SO, 0x64, "SO") - -/* Automatic variable in the stack. Value is offset from frame pointer. - Also used for type descriptions. */ -__define_stab (N_LSYM, 0x80, "LSYM") - -/* Beginning of an include file. Only Sun uses this. - In an object file, only the name is significant. - The Sun linker puts data into some of the other fields. */ -__define_stab (N_BINCL, 0x82, "BINCL") - -/* Name of sub-source file (#include file). - Value is starting text address of the compilation. */ -__define_stab (N_SOL, 0x84, "SOL") - -/* Parameter variable. Value is offset from argument pointer. - (On most machines the argument pointer is the same as the frame pointer. */ -__define_stab (N_PSYM, 0xa0, "PSYM") - -/* End of an include file. No name. - This and N_BINCL act as brackets around the file's output. - In an object file, there is no significant data in this entry. - The Sun linker puts data into some of the fields. */ -__define_stab (N_EINCL, 0xa2, "EINCL") - -/* Alternate entry point. Value is its address. */ -__define_stab (N_ENTRY, 0xa4, "ENTRY") - -/* Beginning of lexical block. - The desc is the nesting level in lexical blocks. - The value is the address of the start of the text for the block. - The variables declared inside the block *precede* the N_LBRAC symbol. */ -__define_stab (N_LBRAC, 0xc0, "LBRAC") - -/* Place holder for deleted include file. Replaces a N_BINCL and everything - up to the corresponding N_EINCL. The Sun linker generates these when - it finds multiple identical copies of the symbols from an include file. - This appears only in output from the Sun linker. */ -__define_stab (N_EXCL, 0xc2, "EXCL") - -/* Modula-2 scope information. Can someone say what info it contains? */ -__define_stab (N_SCOPE, 0xc4, "SCOPE") - -/* End of a lexical block. Desc matches the N_LBRAC's desc. - The value is the address of the end of the text for the block. */ -__define_stab (N_RBRAC, 0xe0, "RBRAC") - -/* Begin named common block. Only the name is significant. */ -__define_stab (N_BCOMM, 0xe2, "BCOMM") - -/* End named common block. Only the name is significant - (and it should match the N_BCOMM). */ -__define_stab (N_ECOMM, 0xe4, "ECOMM") - -/* End common (local name): value is address. - I'm not sure how this is used. */ -__define_stab (N_ECOML, 0xe8, "ECOML") - -/* These STAB's are used on Gould systems for Non-Base register symbols - or something like that. FIXME. I have assigned the values at random - since I don't have a Gould here. Fixups from Gould folk welcome... */ -__define_stab (N_NBTEXT, 0xF0, "NBTEXT") -__define_stab (N_NBDATA, 0xF2, "NBDATA") -__define_stab (N_NBBSS, 0xF4, "NBBSS") -__define_stab (N_NBSTS, 0xF6, "NBSTS") -__define_stab (N_NBLCS, 0xF8, "NBLCS") - -/* Second symbol entry containing a length-value for the preceding entry. - The value is the length. */ -__define_stab (N_LENG, 0xfe, "LENG") - -/* The above information, in matrix format. - - STAB MATRIX - _________________________________________________ - | 00 - 1F are not dbx stab symbols | - | In most cases, the low bit is the EXTernal bit| - - | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | - | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | - - | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | - | 09 |EXT | 0B | 0D | 0F | - - | 10 | 12 COMM | 14 SETA | 16 SETT | - | 11 | 13 | 15 | 17 | - - | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| - | 19 | 1B | 1D | 1F FN | - - |_______________________________________________| - | Debug entries with bit 01 set are unused. | - | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | - | 28 LCSYM | 2A MAIN | 2C | 2E BNSYM | - | 30 PC | 32 NSYMS | 34 NOMAP | 36 | - | 38 OBJ | 3A | 3C OPT | 3E | - | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | - | 48 BSLINE*| 4A DEFD | 4C | 4E ENSYM | - | 50 EHDECL*| 52 | 54 CATCH | 56 | - | 58 | 5A | 5C | 5E | - | 60 SSYM | 62 | 64 SO | 66 | - | 68 | 6A | 6C | 6E | - | 70 | 72 | 74 | 76 | - | 78 | 7A | 7C | 7E | - | 80 LSYM | 82 BINCL | 84 SOL | 86 | - | 88 | 8A | 8C | 8E | - | 90 | 92 | 94 | 96 | - | 98 | 9A | 9C | 9E | - | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | - | A8 | AA | AC | AE | - | B0 | B2 | B4 | B6 | - | B8 | BA | BC | BE | - | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | - | C8 | CA | CC | CE | - | D0 | D2 | D4 | D6 | - | D8 | DA | DC | DE | - | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | - | E8 ECOML | EA | EC | EE | - | F0 | F2 | F4 | F6 | - | F8 | FA | FC | FE LENG | - +-----------------------------------------------+ - * 50 EHDECL is also MOD2. - * 48 BSLINE is also BROWS. - */ diff --git a/gcc/system.h b/gcc/system.h index f8d42ff..c192b6c 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -1009,8 +1009,7 @@ extern void fancy_abort (const char *, int, const char *) ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL HOST_WORDS_BIG_ENDIAN \ OBJC_PROLOGUE ALLOCATE_TRAMPOLINE HANDLE_PRAGMA ROUND_TYPE_SIZE \ ROUND_TYPE_SIZE_UNIT CONST_SECTION_ASM_OP CRT_GET_RFIB_TEXT \ - DBX_LBRAC_FIRST DBX_OUTPUT_ENUM DBX_OUTPUT_SOURCE_FILENAME \ - DBX_WORKING_DIRECTORY INSN_CACHE_DEPTH INSN_CACHE_SIZE \ + INSN_CACHE_DEPTH INSN_CACHE_SIZE \ INSN_CACHE_LINE_WIDTH INIT_SECTION_PREAMBLE NEED_ATEXIT ON_EXIT \ EXIT_BODY OBJECT_FORMAT_ROSE MULTIBYTE_CHARS MAP_CHARACTER \ LIBGCC_NEEDS_DOUBLE FINAL_PRESCAN_LABEL DEFAULT_CALLER_SAVES \ @@ -1023,15 +1022,14 @@ extern void fancy_abort (const char *, int, const char *) MAX_WCHAR_TYPE_SIZE SHARED_SECTION_ASM_OP INTEGRATE_THRESHOLD \ FINAL_REG_PARM_STACK_SPACE MAYBE_REG_PARM_STACK_SPACE \ TRADITIONAL_PIPELINE_INTERFACE DFA_PIPELINE_INTERFACE \ - DBX_OUTPUT_STANDARD_TYPES BUILTIN_SETJMP_FRAME_VALUE \ + BUILTIN_SETJMP_FRAME_VALUE \ SUNOS4_SHARED_LIBRARIES PROMOTE_FOR_CALL_ONLY \ SPACE_AFTER_L_OPTION NO_RECURSIVE_FUNCTION_CSE \ DEFAULT_MAIN_RETURN TARGET_MEM_FUNCTIONS EXPAND_BUILTIN_VA_ARG \ COLLECT_PARSE_FLAG DWARF2_GENERATE_TEXT_SECTION_LABEL WINNING_GDB \ ASM_OUTPUT_FILENAME ASM_OUTPUT_SOURCE_LINE FILE_NAME_JOINER \ - GDB_INV_REF_REGPARM_STABS_LETTER DBX_MEMPARM_STABS_LETTER \ - PUT_SDB_SRC_FILE STABS_GCC_MARKER DBX_OUTPUT_FUNCTION_END \ - DBX_OUTPUT_GCC_MARKER DBX_FINISH_SYMBOL SDB_GENERATE_FAKE \ + GDB_INV_REF_REGPARM_STABS_LETTER \ + PUT_SDB_SRC_FILE STABS_GCC_MARKER SDB_GENERATE_FAKE \ NON_SAVING_SETJMP TARGET_LATE_RTL_PROLOGUE_EPILOGUE \ CASE_DROPS_THROUGH TARGET_BELL TARGET_BS TARGET_CR TARGET_DIGIT0 \ TARGET_ESC TARGET_FF TARGET_NEWLINE TARGET_TAB TARGET_VT \ @@ -1056,8 +1054,8 @@ extern void fancy_abort (const char *, int, const char *) PREFERRED_OUTPUT_RELOAD_CLASS SYSTEM_INCLUDE_DIR \ STANDARD_INCLUDE_DIR STANDARD_INCLUDE_COMPONENT \ LINK_ELIMINATE_DUPLICATE_LDIRECTORIES MIPS_DEBUGGING_INFO \ - IDENT_ASM_OP ALL_COP_ADDITIONAL_REGISTER_NAMES DBX_OUTPUT_LBRAC \ - DBX_OUTPUT_NFUN DBX_OUTPUT_RBRAC RANGE_TEST_NON_SHORT_CIRCUIT \ + IDENT_ASM_OP ALL_COP_ADDITIONAL_REGISTER_NAMES \ + RANGE_TEST_NON_SHORT_CIRCUIT \ REAL_VALUE_TRUNCATE REVERSE_CONDEXEC_PREDICATES_P \ TARGET_ALIGN_ANON_BITFIELDS TARGET_NARROW_VOLATILE_BITFIELDS \ IDENT_ASM_OP UNALIGNED_SHORT_ASM_OP UNALIGNED_INT_ASM_OP \ diff --git a/gcc/target-def.h b/gcc/target-def.h index 1c4aa296..f81f8fe 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -62,8 +62,6 @@ # else # ifdef TARGET_ASM_NAMED_SECTION # define TARGET_ASM_CONSTRUCTOR default_named_section_asm_out_constructor -# else -# define TARGET_ASM_CONSTRUCTOR default_stabs_asm_out_constructor # endif # endif #endif @@ -74,8 +72,6 @@ # else # ifdef TARGET_ASM_NAMED_SECTION # define TARGET_ASM_DESTRUCTOR default_named_section_asm_out_destructor -# else -# define TARGET_ASM_DESTRUCTOR default_stabs_asm_out_destructor # endif # endif #endif diff --git a/gcc/target.def b/gcc/target.def index 8c23066..0e4147e 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1615,6 +1615,9 @@ DEFHOOK "This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float}\n\ fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also\n\ @var{simdlen} field if it was previously 0.\n\ +@var{vecsize_mangle} is a marker for the backend only. @var{vecsize_int} and\n\ +@var{vecsize_float} should be left zero on targets where the number of lanes is\n\ +not determined by the bitsize (in which case @var{simdlen} is always used).\n\ The hook should return 0 if SIMD clones shouldn't be emitted,\n\ or number of @var{vecsize_mangle} variants that should be emitted.", int, (struct cgraph_node *, struct cgraph_simd_clone *, tree, int), NULL) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8f3b3e5..3c5a254 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,556 @@ +2022-09-04 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100136 + * gfortran.dg/PR100136.f90: New test. + +2022-09-03 José Rui Faustino de Sousa <jrfsousa@gmail.com> + + PR fortran/100245 + * gfortran.dg/PR100245.f90: New test. + +2022-09-03 Aldy Hernandez <aldyh@redhat.com> + + * gcc.dg/tree-ssa/pr106819.c: New test. + +2022-09-03 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/doacross-2.c: Adjust expected diagnostics. + * c-c++-common/gomp/doacross-5.c: New test. + * c-c++-common/gomp/doacross-6.c: New test. + * c-c++-common/gomp/nesting-2.c: Adjust expected diagnostics. + * c-c++-common/gomp/ordered-3.c: Likewise. + * c-c++-common/gomp/sink-3.c: Likewise. + * gfortran.dg/gomp/nesting-2.f90: Likewise. + +2022-09-02 David Malcolm <dmalcolm@redhat.com> + + PR c/90885 + * c-c++-common/Wxor-used-as-pow-1.c: New test. + * c-c++-common/Wxor-used-as-pow-fixits.c: New test. + * g++.dg/parse/expr3.C: Convert 2 to 0x2 to suppress + -Wxor-used-as-pow. + * g++.dg/warn/Wparentheses-10.C: Likewise. + * g++.dg/warn/Wparentheses-18.C: Likewise. + * g++.dg/warn/Wparentheses-19.C: Likewise. + * g++.dg/warn/Wparentheses-9.C: Likewise. + * g++.dg/warn/Wxor-used-as-pow-named-op.C: New test. + * gcc.dg/Wparentheses-6.c: Convert 2 to 0x2 to suppress + -Wxor-used-as-pow. + * gcc.dg/Wparentheses-7.c: Likewise. + * gcc.dg/precedence-1.c: Likewise. + +2022-09-02 Harald Anlauf <anlauf@gmx.de> + Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/99349 + * gfortran.dg/pr99349.f90: New test. + +2022-09-02 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/vect/bb-slp-layout-20.c: New test. + +2022-09-02 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/vect/bb-slp-layout-19.c: New test. + +2022-09-02 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106809 + * gcc.dg/torture/pr106809.c: New testcase. + +2022-09-02 Martin Liska <mliska@suse.cz> + + * lib/gcc-dg.exp: Remove -gstabs option support, DBX-related + macros and DBX debugging info support. + * lib/gfortran-dg.exp: Likewise. + * lib/target-supports.exp: Likewise. + * g++.dg/cpp0x/alias-decl-debug-0.C: Removed. + * g++.dg/other/PR23205.C: Removed. + * g++.dg/other/pr23205-2.C: Removed. + * gcc.dg/20040813-1.c: Removed. + * gcc.dg/darwin-20040809-2.c: Removed. + * gcc.dg/debug/pr35154.c: Removed. + * gcc.dg/pr69471-2.c: Removed. + * gcc.target/powerpc/stabs-attrib-vect-darwin.c: Removed. + * gcc.target/s390/20041216-1.c: Removed. + * gfortran.dg/debug/pr35154-stabs.f: Removed. + * objc.dg/stabs-1.m: Removed. + +2022-09-02 Simon Rainer <gcc.gnu@vvalter.com> + + PR ipa/106627 + * g++.target/i386/pr106627.C: New test. + +2022-09-01 H.J. Lu <hjl.tools@gmail.com> + + PR target/106707 + * gcc.target/i386/pr106707.c (foo): Replace long with long long. + +2022-09-01 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/c11-unproto-3.c, gcc.dg/c2x-unproto-3.c, + gcc.dg/c2x-unproto-4.c: New tests. + * gcc.dg/c2x-old-style-definition-6.c, gcc.dg/c2x-unproto-1.c, + gcc.dg/c2x-unproto-2.c: Update for removal of unprototyped + functions. + +2022-09-01 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.dg/vect/bb-slp-pr54400.c: Extend to aarch64. + * gcc.dg/vect/bb-slp-layout-18.c: New test. + +2022-09-01 UroÅ¡ Bizjak <ubizjak@gmail.com> + + PR target/106707 + * gcc.target/i386/pr106707.c: New test. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + * gcc.dg/tree-ssa/vrp-float-signbit-1.c: New test. + +2022-09-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/106655 + * c-c++-common/cpp/Winvalid-utf8-1.c: New test. + * c-c++-common/cpp/Winvalid-utf8-2.c: New test. + * c-c++-common/cpp/Winvalid-utf8-3.c: New test. + * g++.dg/cpp23/Winvalid-utf8-1.C: New test. + * g++.dg/cpp23/Winvalid-utf8-2.C: New test. + * g++.dg/cpp23/Winvalid-utf8-3.C: New test. + * g++.dg/cpp23/Winvalid-utf8-4.C: New test. + * g++.dg/cpp23/Winvalid-utf8-5.C: New test. + * g++.dg/cpp23/Winvalid-utf8-6.C: New test. + * g++.dg/cpp23/Winvalid-utf8-7.C: New test. + * g++.dg/cpp23/Winvalid-utf8-8.C: New test. + * g++.dg/cpp23/Winvalid-utf8-9.C: New test. + * g++.dg/cpp23/Winvalid-utf8-10.C: New test. + * g++.dg/cpp23/Winvalid-utf8-11.C: New test. + * g++.dg/cpp23/Winvalid-utf8-12.C: New test. + +2022-09-01 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/106785 + * gcc.dg/tree-ssa/vrp-float-nan-1.c: New test. + +2022-09-01 konglin1 <lingling.kong@intel.com> + + * gcc.dg/tree-ssa/gen-vect-34.c: New test. + * gcc.dg/vect/vect-ifcvt-18.c: New test. + +2022-09-01 Kewen Lin <linkw@linux.ibm.com> + + PR testsuite/106682 + * gcc.target/powerpc/pr86731-fwrapv-longlong.c: Fix typo. + +2022-09-01 Peter Bergner <bergner@linux.ibm.com> + + PR target/101322 + * g++.target/powerpc/pr101322.C: New test. + +2022-08-31 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/c2x-attr-deprecated-2.c, gcc.dg/c2x-attr-fallthrough-2.c, + gcc.dg/c2x-attr-maybe_unused-1.c, gcc.dg/c2x-attr-nodiscard-2.c: + Add tests of attributes on labels. + * gcc.dg/c2x-has-c-attribute-2.c: Update expected results for + maybe_unused and fallthrough. + +2022-08-31 Martin Liska <mliska@suse.cz> + + * g++.dg/cpp0x/lambda/lambda-conv.C: Remove useless test. + * gcc.c-torture/execute/ieee/hugeval.x: Likewise. + * gcc.dg/torture/pr47917.c: Likewise. + * lib/target-supports.exp: Likewise. + +2022-08-31 Jonathan Wakely <jwakely@redhat.com> + + PR testsuite/106795 + * g++.dg/tree-ssa/empty-loop.C: Use -Wno-unused-result. + +2022-08-31 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c: Update + tests for empty initializers. + * gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general-c/sizeless-1.c: Likewise. + * gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Likewise. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/90994 + * g++.dg/torture/pr90994.C: New testcase. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/65244 + * gcc.dg/uninit-pr65244-2.c: New testcase. + +2022-08-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/65244 + * gcc.dg/uninit-pr65244-1.c: New testcase. + +2022-08-30 Andrew Stubbs <ams@codesourcery.com> + + * gcc.dg/vect/vect-simd-clone-1.c: Add dg-warning. + * gcc.dg/vect/vect-simd-clone-2.c: Add dg-warning. + * gcc.dg/vect/vect-simd-clone-3.c: Add dg-warning. + * gcc.dg/vect/vect-simd-clone-4.c: Add dg-warning. + * gcc.dg/vect/vect-simd-clone-5.c: Add dg-warning. + * gcc.dg/vect/vect-simd-clone-8.c: Add dg-warning. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * lib/target-supports.exp (check_effective_target_vect_var_shift): + Return true for aarch64. + * gcc.dg/vect/bb-slp-layout-1.c: New test. + * gcc.dg/vect/bb-slp-layout-2.c: New test. + * gcc.dg/vect/bb-slp-layout-3.c: New test. + * gcc.dg/vect/bb-slp-layout-4.c: New test. + * gcc.dg/vect/bb-slp-layout-5.c: New test. + * gcc.dg/vect/bb-slp-layout-6.c: New test. + * gcc.dg/vect/bb-slp-layout-7.c: New test. + * gcc.dg/vect/bb-slp-layout-8.c: New test. + * gcc.dg/vect/bb-slp-layout-9.c: New test. + * gcc.dg/vect/bb-slp-layout-10.c: New test. + * gcc.dg/vect/bb-slp-layout-11.c: New test. + * gcc.dg/vect/bb-slp-layout-13.c: New test. + * gcc.dg/vect/bb-slp-layout-14.c: New test. + * gcc.dg/vect/bb-slp-layout-15.c: New test. + * gcc.dg/vect/bb-slp-layout-16.c: New test. + * gcc.dg/vect/bb-slp-layout-17.c: New test. + * gcc.dg/vect/slp-11b.c: XFAIL SLP test for load-lanes targets. + * gcc.dg/vect/bb-slp-layout-12.c: New file. + +2022-08-30 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/slp_15.c: New test. + * g++.target/aarch64/sve/pr96974.C: Remove scan test. + +2022-08-30 Marek Polacek <polacek@redhat.com> + + PR c++/106759 + * g++.dg/ext/has-builtin-1.C: New test. + +2022-08-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/67196 + * gcc.dg/uninit-pred-7_a.c: Un-XFAIL. + +2022-08-30 Aldy Hernandez <aldyh@redhat.com> + + * gcc.dg/tree-ssa/recip-3.c: Avoid premature optimization so test + has a chance to succeed. + +2022-08-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/63660 + * gcc.dg/uninit-pr63660.c: New testcase. + +2022-08-30 Richard Biener <rguenther@suse.de> + + * g++.dg/uninit-pred-5.C: New testcase. + +2022-08-30 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/106744 + * gcc.dg/tree-ssa/minmax-10.c: Make runtime test. + * gcc.dg/tree-ssa/minmax-11.c: Likewise. + * gcc.dg/tree-ssa/minmax-12.c: Likewise. + * gcc.dg/tree-ssa/minmax-13.c: Likewise. + * gcc.dg/tree-ssa/minmax-14.c: Likewise. + * gcc.dg/tree-ssa/minmax-15.c: Likewise. + * gcc.dg/tree-ssa/minmax-16.c: Likewise. + * gcc.dg/tree-ssa/minmax-3.c: Likewise. + * gcc.dg/tree-ssa/minmax-4.c: Likewise. + * gcc.dg/tree-ssa/minmax-5.c: Likewise. + * gcc.dg/tree-ssa/minmax-6.c: Likewise. + * gcc.dg/tree-ssa/minmax-7.c: Likewise. + * gcc.dg/tree-ssa/minmax-8.c: Likewise. + * gcc.dg/tree-ssa/minmax-9.c: Likewise. + +2022-08-29 Marek Polacek <polacek@redhat.com> + + PR c++/106712 + * g++.dg/cpp0x/gen-attrs-77.C: New test. + +2022-08-29 David Faust <david.faust@oracle.com> + + PR target/106745 + * gcc.target/bpf/core-pr106745.c: New test. + +2022-08-29 H.J. Lu <hjl.tools@gmail.com> + + PR target/106748 + * gcc.target/i386/pr106748.c: New test. + +2022-08-29 Xi Ruoyao <xry111@xry111.site> + + * gcc.target/loongarch/func-call-medium-1.c: Refine test + depending on __tls_get_addr with { target tls_native }. + * gcc.target/loongarch/func-call-medium-2.c: Likewise. + * gcc.target/loongarch/func-call-medium-3.c: Likewise. + * gcc.target/loongarch/func-call-medium-4.c: Likewise. + * gcc.target/loongarch/func-call-medium-5.c: Likewise. + * gcc.target/loongarch/func-call-medium-6.c: Likewise. + * gcc.target/loongarch/func-call-medium-7.c: Likewise. + * gcc.target/loongarch/func-call-medium-8.c: Likewise. + * gcc.target/loongarch/tls-gd-noplt.c: Likewise. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * gcc.target/s390/vector/vec-sum-across-no-lower-subreg-1.c: New test. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * gcc.target/s390/vector/vperm-rev-z14.c: New test. + * gcc.target/s390/vector/vperm-rev-z15.c: New test. + * gcc.target/s390/zvector/vec-reve-store-byte.c: Adjust test + expectation. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * gcc.target/s390/zvector/vec-reve-int-long.c: New test. + +2022-08-29 Robin Dapp <rdapp@linux.ibm.com> + + * gcc.target/s390/vector/vec-copysign.c: Do not unroll. + * gcc.target/s390/zvector/autovec-double-quiet-uneq.c: Dito. + * gcc.target/s390/zvector/autovec-double-signaling-ltgt.c: Dito. + * gcc.target/s390/zvector/autovec-float-quiet-uneq.c: Dito. + * gcc.target/s390/zvector/autovec-float-signaling-ltgt.c: Dito. + +2022-08-28 Peter Bergner <bergner@linux.ibm.com> + + PR target/106017 + * gcc.target/powerpc/pr106017.c: New test. + +2022-08-27 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/106737 + * gcc.dg/autopar/pr106737.c: Require fgraphite effective target. + +2022-08-26 Marek Polacek <polacek@redhat.com> + + PR c++/81159 + * g++.dg/warn/Wself-move1.C: New test. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/106647 + * g++.dg/cpp23/wchar-multi1.C: New test. + * g++.dg/cpp23/wchar-multi2.C: New test. + +2022-08-26 Richard Biener <rguenther@suse.de> + + * gcc.dg/uninit-pred-11.c: New testcase. + +2022-08-26 Tobias Burnus <tobias@codesourcery.com> + + * c-c++-common/gomp/reverse-offload-1.c: Remove dg-sorry. + * c-c++-common/gomp/target-device-ancestor-4.c: Likewise. + * gfortran.dg/gomp/target-device-ancestor-4.f90: Likewise. + * gfortran.dg/gomp/target-device-ancestor-5.f90: Likewise. + * c-c++-common/goacc/classify-kernels-parloops.c: Add 'noclone' to + scan-tree-dump-times. + * c-c++-common/goacc/classify-kernels-unparallelized-parloops.c: + Likewise. + * c-c++-common/goacc/classify-kernels-unparallelized.c: Likewise. + * c-c++-common/goacc/classify-kernels.c: Likewise. + * c-c++-common/goacc/classify-parallel.c: Likewise. + * c-c++-common/goacc/classify-serial.c: Likewise. + * c-c++-common/goacc/kernels-counter-vars-function-scope.c: Likewise. + * c-c++-common/goacc/kernels-loop-2.c: Likewise. + * c-c++-common/goacc/kernels-loop-3.c: Likewise. + * c-c++-common/goacc/kernels-loop-data-2.c: Likewise. + * c-c++-common/goacc/kernels-loop-data-enter-exit-2.c: Likewise. + * c-c++-common/goacc/kernels-loop-data-enter-exit.c: Likewise. + * c-c++-common/goacc/kernels-loop-data-update.c: Likewise. + * c-c++-common/goacc/kernels-loop-data.c: Likewise. + * c-c++-common/goacc/kernels-loop-g.c: Likewise. + * c-c++-common/goacc/kernels-loop-mod-not-zero.c: Likewise. + * c-c++-common/goacc/kernels-loop-n.c: Likewise. + * c-c++-common/goacc/kernels-loop-nest.c: Likewise. + * c-c++-common/goacc/kernels-loop.c: Likewise. + * c-c++-common/goacc/kernels-one-counter-var.c: Likewise. + * c-c++-common/goacc/kernels-parallel-loop-data-enter-exit.c: Likewise. + * gfortran.dg/goacc/classify-kernels-parloops.f95: Likewise. + * gfortran.dg/goacc/classify-kernels-unparallelized-parloops.f95: + Likewise. + * gfortran.dg/goacc/classify-kernels-unparallelized.f95: Likewise. + * gfortran.dg/goacc/classify-kernels.f95: Likewise. + * gfortran.dg/goacc/classify-parallel.f95: Likewise. + * gfortran.dg/goacc/classify-serial.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-2.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-data-2.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-data-enter-exit-2.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-data-enter-exit.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-data-update.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-data.f95: Likewise. + * gfortran.dg/goacc/kernels-loop-n.f95: Likewise. + * gfortran.dg/goacc/kernels-loop.f95: Likewise. + * gfortran.dg/goacc/kernels-parallel-loop-data-enter-exit.f95: Likewise. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/torture/builtin-issignaling-1.c: New test. + * gcc.dg/torture/builtin-issignaling-2.c: New test. + * gcc.dg/torture/float16-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float32-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float32x-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float64-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float64x-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float128-builtin-issignaling-1.c: New test. + * gcc.dg/torture/float128x-builtin-issignaling-1.c: New test. + * gcc.target/i386/builtin-issignaling-1.c: New test. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/106099 + * gcc.dg/pr106099.c: New test. + +2022-08-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/106648 + * c-c++-common/cpp/named-universal-char-escape-1.c: New test. + * c-c++-common/cpp/named-universal-char-escape-2.c: New test. + * c-c++-common/cpp/named-universal-char-escape-3.c: New test. + * c-c++-common/cpp/named-universal-char-escape-4.c: New test. + * c-c++-common/Wbidi-chars-25.c: New test. + * gcc.dg/cpp/named-universal-char-escape-1.c: New test. + * gcc.dg/cpp/named-universal-char-escape-2.c: New test. + * g++.dg/cpp/named-universal-char-escape-1.C: New test. + * g++.dg/cpp/named-universal-char-escape-2.C: New test. + * g++.dg/cpp23/feat-cxx2b.C: Test __cpp_named_character_escapes. + +2022-08-26 Martin Liska <mliska@suse.cz> + + * lib/target-supports.exp: Remove cr16 related stuff. + +2022-08-26 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr106704.c: New test. + +2022-08-25 Marek Polacek <polacek@redhat.com> + + * gcc.dg/c11-nullptr-1.c: New test. + * gcc.dg/c17-nullptr-1.c: New test. + * gcc.dg/c17-nullptr-2.c: New test. + * gcc.dg/c2x-nullptr-1.c: New test. + * gcc.dg/c2x-nullptr-2.c: New test. + * gcc.dg/c2x-nullptr-3.c: New test. + * gcc.dg/c2x-nullptr-4.c: New test. + * gcc.dg/c2x-nullptr-5.c: New test. + +2022-08-25 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/c11-empty-init-1.c, gcc.dg/c11-empty-init-2.c, + gcc.dg/c11-empty-init-3.c, gcc.dg/c2x-empty-init-1.c, + gcc.dg/c2x-empty-init-2.c, gcc.dg/c2x-empty-init-3.c, + gcc.dg/gnu2x-empty-init-1.c, gcc.dg/gnu2x-empty-init-2.c: New + tests. + * gcc.dg/torture/dfp-default-init-1.c: Also test empty + initializers. + * gcc.dg/init-bad-1.c, gcc.dg/noncompile/pr71583.c, + gcc.dg/pr61096-1.c, gcc.dg/vla-init-2.c, gcc.dg/vla-init-3.c, + gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Update expected + diagnostics. + * gcc.dg/ubsan/c-shift-1.c: Use nonempty initializers for VLA + initializations expected to be diagnosed. + +2022-08-25 Jason Merrill <jason@redhat.com> + + * g++.dg/init/elide8.C: New test. + +2022-08-25 Jason Merrill <jason@redhat.com> + + * g++.dg/debug/dwarf2/utf-1.C: New test. + +2022-08-25 Andreas Krebbel <krebbel@linux.ibm.com> + + PR target/106101 + * gcc.c-torture/compile/pr106101.c: New test. + +2022-08-25 Xi Ruoyao <xry111@xry111.site> + + * gcc.target/loongarch/attr-model-test.c: New test. + * gcc.target/loongarch/attr-model-1.c: New test. + * gcc.target/loongarch/attr-model-2.c: New test. + * gcc.target/loongarch/attr-model-diag.c: New test. + +2022-08-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/106737 + * gcc.dg/autopar/pr106737.c: New testcase. + +2022-08-25 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.dg/gomp/strictly-structured-block-4.f90: New test. + +2022-08-25 Chenghua Xu <xuchenghua@loongson.cn> + + * gcc.target/loongarch/pr106459.c: New test. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + * lib/target-supports.exp (check_effective_target_bswap): + Return true if riscv and ZBB ISA extension is enabled. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106601 + * gcc.target/riscv/zbb_32_bswap-2.c: New test. + * gcc.target/riscv/zbb_bswap-2.c: New test. + +2022-08-24 Andrew Pinski <apinski@marvell.com> + + PR target/106600 + * gcc.target/riscv/zbb_32_bswap-1.c: New test. + * gcc.target/riscv/zbb_bswap-1.c: New test. + +2022-08-24 Harald Anlauf <anlauf@gmx.de> + + PR fortran/103694 + * gfortran.dg/pr103694.f90: New test. + +2022-08-24 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/torture/dfp-default-init-1.c, + gcc.dg/torture/dfp-default-init-2.c, + gcc.dg/torture/dfp-default-init-3.c: New tests. + +2022-08-24 Jose E. Marchesi <jose.marchesi@oracle.com> + + PR target/106733 + * gcc.target/bpf/constant-calls.c: Rename to ... + * gcc.target/bpf/constant-calls-1.c: and modify to not expect + failure anymore. + * gcc.target/bpf/constant-calls-2.c: New test. + +2022-08-24 Jakub Jelinek <jakub@redhat.com> + + PR target/106721 + * gcc.target/i386/avx512vl-pr106721.c: New test. + +2022-08-24 Jakub Jelinek <jakub@redhat.com> + + PR c++/106646 + * g++.dg/cpp/warning-1.C: New test. + * g++.dg/cpp/warning-2.C: New test. + * g++.dg/cpp/warning-3.C: New test. + +2022-08-24 Lulu Cheng <chenglulu@loongson.cn> + + * gcc.target/loongarch/func-call-medium-1.c: New test. + * gcc.target/loongarch/func-call-medium-2.c: New test. + * gcc.target/loongarch/func-call-medium-3.c: New test. + * gcc.target/loongarch/func-call-medium-4.c: New test. + * gcc.target/loongarch/func-call-medium-5.c: New test. + * gcc.target/loongarch/func-call-medium-6.c: New test. + * gcc.target/loongarch/func-call-medium-7.c: New test. + * gcc.target/loongarch/func-call-medium-8.c: New test. + * gcc.target/loongarch/tls-gd-noplt.c: Add compile parameter '-mexplicit-relocs'. + 2022-08-23 Marek Polacek <polacek@redhat.com> * g++.dg/cpp0x/Wpessimizing-move10.C: New test. diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-25.c b/gcc/testsuite/c-c++-common/Wbidi-chars-25.c new file mode 100644 index 0000000..58d6a29 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wbidi-chars-25.c @@ -0,0 +1,28 @@ +/* PR preprocessor/103026 */ +/* { dg-do compile } */ +/* { dg-options "-Wbidi-chars=ucn,unpaired" } */ +/* Test nesting of bidi chars in various contexts. */ + +void +g1 () +{ + const char *s1 = "a b c LRE\N{LEFT-TO-RIGHT EMBEDDING} 1 2 3 PDI\N{POP DIRECTIONAL ISOLATE} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s2 = "a b c RLE\N{RIGHT-TO-LEFT EMBEDDING} 1 2 3 PDI\N{POP DIRECTIONAL ISOLATE} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s3 = "a b c LRO\N{LEFT-TO-RIGHT OVERRIDE} 1 2 3 PDI\N{POP DIRECTIONAL ISOLATE} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s4 = "a b c RLO\N{RIGHT-TO-LEFT OVERRIDE} 1 2 3 PDI\N{POP DIRECTIONAL ISOLATE} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s5 = "a b c LRI\N{LEFT-TO-RIGHT ISOLATE} 1 2 3 PDF\N{POP DIRECTIONAL FORMATTING} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s6 = "a b c RLI\N{RIGHT-TO-LEFT ISOLATE} 1 2 3 PDF\N{POP DIRECTIONAL FORMATTING} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ + const char *s7 = "a b c FSI\N{FIRST STRONG ISOLATE} 1 2 3 PDF\N{POP DIRECTIONAL FORMATTING} x y z"; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ +} + +int A\N{LEFT-TO-RIGHT EMBEDDING}B\N{POP DIRECTIONAL ISOLATE}C; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ +int a\N{RIGHT-TO-LEFT EMBEDDING}B\N{POP DIRECTIONAL ISOLATE}c; +/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/Wxor-used-as-pow-1.c b/gcc/testsuite/c-c++-common/Wxor-used-as-pow-1.c new file mode 100644 index 0000000..962902c --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wxor-used-as-pow-1.c @@ -0,0 +1,57 @@ +/* The precise output depends of sizeof(int) and sizeof(long long), so + filter by target. */ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ + +/* Apparent uses of ^ for powers of 2. */ + +short t2_16 = 2^16; /* { dg-warning "result of '2\\^16' is 18; did you mean '1 << 16' \\(65536\\)\\? \\\[-Wxor-used-as-pow\\\]" } */ +int t2_17 = 2^17; /* { dg-warning "result of '2\\^17' is 19; did you mean '1 << 17' \\(131072\\)\\?" } */ +int t2_30 = 2^30; /* { dg-warning "result of '2\\^30' is 28; did you mean '1 << 30' \\(1073741824\\)\\?" } */ + +/* Should be 1LL at 31 and above, due to overflow. */ +int t2_31 = 2^31; /* { dg-warning "result of '2\\^31' is 29; did you mean '1LL << 31'\\?" } */ +int t2_32 = 2^32; /* { dg-warning "result of '2\\^32' is 34; did you mean '1LL << 32'\\?" } */ + +long t2_63 = 2^63; /* { dg-warning "result of '2\\^63' is 61; did you mean exponentiation\\?" } */ +long t2_64 = 2^64; /* { dg-warning "result of '2\\^64' is 66; did you mean exponentiation\\?" } */ + +/* ...but don't warn when RHS is large enough. */ +long t2_65 = 2^65; +long t2_127 = 2^127; +long t2_128 = 2^128; +long t2_129 = 2^129; + +/* Verify that -Wxor-used-as-pow happens before folding. */ +long t2_32_m1 = ((2^32)-1); /* { dg-warning "result of '2\\^32' is 34; did you mean '1LL << 32'\\?" } */ + + +/* Apparent uses of ^ for powers of 10. */ + +long t10_2 = 10^2; /* { dg-warning "result of '10\\^2' is 8; did you mean '1e2'\\?" } */ +long t10_9 = 10^9; /* { dg-warning "result of '10\\^9' is 3; did you mean '1e9'\\?" } */ +long t10_10 = 10^10; /* { dg-warning "result of '10\\^10' is 0; did you mean '1e10'\\?" } */ +long t10_100 = 10^100; /* { dg-warning "result of '10\\^100' is 110; did you mean '1e100'\\?" } */ + +/* Don't warn on negatives. */ +long tm2_2 = -2^2; +long t2_m2 = 2^-2; +long tm10_10 = -10^10; +long t10_m10 = 10^-10; + +/* If LHS is not 2 or 10, we shouldn't complain. */ +int t0_0 = 0 ^ 0; +int t6_7 = 6 ^ 7; + +/* Floating point is already covered by type-checking. */ +float f10_10 = 10.f^10; /* { dg-error "invalid operands to binary \\^ \\(have 'float' and 'int'\\)" "" { target c } } */ +/* { dg-error "invalid operands of types 'float' and 'int' to binary 'operator\\^'" "" { target c++ } .-1 } */ + +/* Don't complain if the LHS isn't literal decimal 2 or 10. */ +int t1p1_16 = (1 + 1) ^ 16; +int t5p5_6 = (5 + 5) ^ 6; +int h2_8 = 0x2 ^ 8; +int h10_3 = 0xa ^ 3; + +/* Don't complain if the RHS isn't literal decimal. */ +int t2_x16 = 2^0x10; +int h10_x3 = 10 ^ 0x3; diff --git a/gcc/testsuite/c-c++-common/Wxor-used-as-pow-fixits.c b/gcc/testsuite/c-c++-common/Wxor-used-as-pow-fixits.c new file mode 100644 index 0000000..f612b76 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wxor-used-as-pow-fixits.c @@ -0,0 +1,34 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +/* Test fixit hints for -Wxor-used-as-pow. */ + +int t2_8 = 2^8; /* { dg-line line_a } */ +/* { dg-warning "result of '2\\^8' is 10; did you mean '1 << 8' \\(256\\)\\?" "warn" { target *-*-* } line_a } */ +/* { dg-begin-multiline-output "" } + int t2_8 = 2^8; + ^ + -- + 1<< + { dg-end-multiline-output "" } */ +/* { dg-message "you can silence this warning by using a hexadecimal constant \\(0x2 rather than 2\\)" "note" { target *-*-* } line_a } */ +/* { dg-begin-multiline-output "" } + int t2_8 = 2^8; + ^ + 0x2 + { dg-end-multiline-output "" } */ + + +int t10_6 = 10^6; /* { dg-line line_b } */ +/* { dg-warning "result of '10\\^6' is 12; did you mean '1e6'\\?" "warn" { target *-*-* } line_b } */ +/* { dg-begin-multiline-output "" } + int t10_6 = 10^6; + ^ + --- + 1e + { dg-end-multiline-output "" } */ +/* { dg-message "you can silence this warning by using a hexadecimal constant \\(0xa rather than 10\\)" "note" { target *-*-* } line_b } */ +/* { dg-begin-multiline-output "" } + int t10_6 = 10^6; + ^~ + 0xa + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-1.c b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-1.c new file mode 100644 index 0000000..0d5a6a7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-1.c @@ -0,0 +1,43 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -Winvalid-utf8" } + +// aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } +// a€a { dg-warning "invalid UTF-8 character <80>" } +// a¿a { dg-warning "invalid UTF-8 character <bf>" } +// aÀa { dg-warning "invalid UTF-8 character <c0>" } +// aÁa { dg-warning "invalid UTF-8 character <c1>" } +// aõa { dg-warning "invalid UTF-8 character <f5>" } +// aÿa { dg-warning "invalid UTF-8 character <ff>" } +// aÂa { dg-warning "invalid UTF-8 character <c2>" } +// aàa { dg-warning "invalid UTF-8 character <e0>" } +// aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" } +// aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" } +// aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" } +// aì€a { dg-warning "invalid UTF-8 character <ec><80>" } +// aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" } +// að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +// að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +// aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" } +// aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } +// { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } +/* aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } */ +/* a€a { dg-warning "invalid UTF-8 character <80>" } */ +/* a¿a { dg-warning "invalid UTF-8 character <bf>" } */ +/* aÀa { dg-warning "invalid UTF-8 character <c0>" } */ +/* aÁa { dg-warning "invalid UTF-8 character <c1>" } */ +/* aõa { dg-warning "invalid UTF-8 character <f5>" } */ +/* aÿa { dg-warning "invalid UTF-8 character <ff>" } */ +/* aÂa { dg-warning "invalid UTF-8 character <c2>" } */ +/* aàa { dg-warning "invalid UTF-8 character <e0>" } */ +/* aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" } */ +/* aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" } */ +/* aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" } */ +/* aì€a { dg-warning "invalid UTF-8 character <ec><80>" } */ +/* aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" } */ +/* að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" } */ +/* að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } */ +/* aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" } */ +/* aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } */ +/* { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-2.c b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-2.c new file mode 100644 index 0000000..9ab69e1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-2.c @@ -0,0 +1,88 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess { target { c || c++11 } } } +// { dg-require-effective-target wchar } +// { dg-options "-finput-charset=UTF-8 -Winvalid-utf8" } +// { dg-additional-options "-std=gnu99" { target c } } + +#ifndef __cplusplus +#include <wchar.h> +typedef __CHAR16_TYPE__ char16_t; +typedef __CHAR32_TYPE__ char32_t; +#endif + +char32_t a = U'€'; // { dg-warning "invalid UTF-8 character <80>" } +char32_t b = U'¿'; // { dg-warning "invalid UTF-8 character <bf>" } +char32_t c = U'À'; // { dg-warning "invalid UTF-8 character <c0>" } +char32_t d = U'Á'; // { dg-warning "invalid UTF-8 character <c1>" } +char32_t e = U'õ'; // { dg-warning "invalid UTF-8 character <f5>" } +char32_t f = U'ÿ'; // { dg-warning "invalid UTF-8 character <ff>" } +char32_t g = U'Â'; // { dg-warning "invalid UTF-8 character <c2>" } +char32_t h = U'à'; // { dg-warning "invalid UTF-8 character <e0>" } +char32_t i = U'à€¿'; // { dg-warning "invalid UTF-8 character <e0><80><bf>" } +char32_t j = U'àŸ€'; // { dg-warning "invalid UTF-8 character <e0><9f><80>" } +char32_t k = U'à¿'; // { dg-warning "invalid UTF-8 character <e0><bf>" } +char32_t l = U'ì€'; // { dg-warning "invalid UTF-8 character <ec><80>" } +char32_t m = U'í €'; // { dg-warning "invalid UTF-8 character <ed><a0><80>" } +char32_t n = U'ð€€€'; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +char32_t o = U'ð¿¿'; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +char32_t p = U'ô€€'; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" } +char32_t q = U'ý¿¿¿¿¿'; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } + // { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } +const char32_t *A = U"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +const char32_t *B = U"€"; // { dg-warning "invalid UTF-8 character <80>" } +const char32_t *C = U"¿"; // { dg-warning "invalid UTF-8 character <bf>" } +const char32_t *D = U"À"; // { dg-warning "invalid UTF-8 character <c0>" } +const char32_t *E = U"Á"; // { dg-warning "invalid UTF-8 character <c1>" } +const char32_t *F = U"õ"; // { dg-warning "invalid UTF-8 character <f5>" } +const char32_t *G = U"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" } +const char32_t *H = U"Â"; // { dg-warning "invalid UTF-8 character <c2>" } +const char32_t *I = U"à"; // { dg-warning "invalid UTF-8 character <e0>" } +const char32_t *J = U"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" } +const char32_t *K = U"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" } +const char32_t *L = U"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" } +const char32_t *M = U"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" } +const char32_t *N = U"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" } +const char32_t *O = U"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +const char32_t *P = U"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +const char32_t *Q = U"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" } +const char32_t *R = U"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } + // { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } +const char32_t *A1 = UR"(Â€ß¿à €íŸ¿î€€ð€€ô¿¿)"; // { dg-bogus "invalid UTF-8 character" } +const char32_t *B1 = UR"(€)"; // { dg-warning "invalid UTF-8 character <80>" } +const char32_t *C1 = UR"(¿)"; // { dg-warning "invalid UTF-8 character <bf>" } +const char32_t *D1 = UR"(À)"; // { dg-warning "invalid UTF-8 character <c0>" } +const char32_t *E1 = UR"(Á)"; // { dg-warning "invalid UTF-8 character <c1>" } +const char32_t *F1 = UR"(õ)"; // { dg-warning "invalid UTF-8 character <f5>" } +const char32_t *G1 = UR"(ÿ)"; // { dg-warning "invalid UTF-8 character <ff>" } +const char32_t *H1 = UR"(Â)"; // { dg-warning "invalid UTF-8 character <c2>" } +const char32_t *I1 = UR"(à)"; // { dg-warning "invalid UTF-8 character <e0>" } +const char32_t *J1 = UR"(à€¿)"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" } +const char32_t *K1 = UR"(àŸ€)"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" } +const char32_t *L1 = UR"(à¿)"; // { dg-warning "invalid UTF-8 character <e0><bf>" } +const char32_t *M1 = UR"(ì€)"; // { dg-warning "invalid UTF-8 character <ec><80>" } +const char32_t *N1 = UR"(í €)"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" } +const char32_t *O1 = UR"(ð€€€)"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +const char32_t *P1 = UR"(ð¿¿)"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +const char32_t *Q1 = UR"(ô€€)"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" } +const char32_t *R1 = UR"(ý¿¿¿¿¿)"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } + // { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } +const char *A2 = u8"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +const char *B2 = u8"€"; // { dg-warning "invalid UTF-8 character <80>" } +const char *C2 = u8"¿"; // { dg-warning "invalid UTF-8 character <bf>" } +const char *D2 = u8"À"; // { dg-warning "invalid UTF-8 character <c0>" } +const char *E2 = u8"Á"; // { dg-warning "invalid UTF-8 character <c1>" } +const char *F2 = u8"õ"; // { dg-warning "invalid UTF-8 character <f5>" } +const char *G2 = u8"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" } +const char *H2 = u8"Â"; // { dg-warning "invalid UTF-8 character <c2>" } +const char *I2 = u8"à"; // { dg-warning "invalid UTF-8 character <e0>" } +const char *J2 = u8"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" } +const char *K2 = u8"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" } +const char *L2 = u8"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" } +const char *M2 = u8"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" } +const char *N2 = u8"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" } +const char *O2 = u8"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +const char *P2 = u8"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +const char *Q2 = u8"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" } +const char *R2 = u8"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" } + // { dg-warning "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-3.c b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-3.c new file mode 100644 index 0000000..4cb230f --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/Winvalid-utf8-3.c @@ -0,0 +1,27 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -Winvalid-utf8" } + +#define I(x) +I(Â€ß¿à €íŸ¿î€€ð€€ô¿¿) // { dg-bogus "invalid UTF-8 character" } + // { dg-error "is not valid in an identifier" "" { target c++ } .-1 } +I(€) // { dg-warning "invalid UTF-8 character <80>" } +I(¿) // { dg-warning "invalid UTF-8 character <bf>" } +I(À) // { dg-warning "invalid UTF-8 character <c0>" } +I(Á) // { dg-warning "invalid UTF-8 character <c1>" } +I(õ) // { dg-warning "invalid UTF-8 character <f5>" } +I(ÿ) // { dg-warning "invalid UTF-8 character <ff>" } +I(Â) // { dg-warning "invalid UTF-8 character <c2>" } +I(à) // { dg-warning "invalid UTF-8 character <e0>" } +I(à€¿) // { dg-warning "invalid UTF-8 character <e0><80><bf>" } +I(àŸ€) // { dg-warning "invalid UTF-8 character <e0><9f><80>" } +I(à¿) // { dg-warning "invalid UTF-8 character <e0><bf>" } +I(ì€) // { dg-warning "invalid UTF-8 character <ec><80>" } +I(í €) // { dg-warning "invalid UTF-8 character <ed><a0><80>" } +I(ð€€€) // { dg-warning "invalid UTF-8 character <f0><80><80><80>" } +I(ð¿¿) // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" } +I(ô€€) // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c } } + // { dg-error "is not valid in an identifier" "" { target c++ } .-1 } +I(ý¿¿¿¿¿) // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c } } + // { dg-error "is not valid in an identifier" "" { target c++ } .-1 } diff --git a/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-1.c b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-1.c new file mode 100644 index 0000000..3c692f45 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-1.c @@ -0,0 +1,174 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do run } */ +/* { dg-require-effective-target wchar } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat" { target c } } */ +/* { dg-options "-std=c++23" { target c++ } } */ + +#ifndef __cplusplus +#include <wchar.h> +typedef __CHAR16_TYPE__ char16_t; +typedef __CHAR32_TYPE__ char32_t; +#endif + +#ifdef __cplusplus +#if U'\u0000' != U'\N{NULL}' \ + || U'\u0001' != U'\N{START OF HEADING}' \ + || U'\u0002' != U'\N{START OF TEXT}' \ + || U'\u0003' != U'\N{END OF TEXT}' \ + || U'\u0004' != U'\N{END OF TRANSMISSION}' \ + || U'\u0005' != U'\N{ENQUIRY}' \ + || U'\u0006' != U'\N{ACKNOWLEDGE}' \ + || U'\u0007' != U'\N{ALERT}' \ + || U'\u0008' != U'\N{BACKSPACE}' \ + || U'\u0009' != U'\N{CHARACTER TABULATION}' \ + || U'\u0009' != U'\N{HORIZONTAL TABULATION}' \ + || U'\u000A' != U'\N{LINE FEED}' \ + || U'\u000A' != U'\N{NEW LINE}' \ + || U'\u000A' != U'\N{END OF LINE}' \ + || U'\u000B' != U'\N{LINE TABULATION}' \ + || U'\u000B' != U'\N{VERTICAL TABULATION}' \ + || U'\u000C' != U'\N{FORM FEED}' \ + || U'\u000D' != U'\N{CARRIAGE RETURN}' \ + || U'\u000E' != U'\N{SHIFT OUT}' \ + || U'\u000E' != U'\N{LOCKING-SHIFT ONE}' \ + || U'\u000F' != U'\N{SHIFT IN}' \ + || U'\u000F' != U'\N{LOCKING-SHIFT ZERO}' \ + || U'\u0010' != U'\N{DATA LINK ESCAPE}' \ + || U'\u0011' != U'\N{DEVICE CONTROL ONE}' \ + || U'\u0012' != U'\N{DEVICE CONTROL TWO}' \ + || U'\u0013' != U'\N{DEVICE CONTROL THREE}' \ + || U'\u0014' != U'\N{DEVICE CONTROL FOUR}' \ + || U'\u0015' != U'\N{NEGATIVE ACKNOWLEDGE}' \ + || U'\u0016' != U'\N{SYNCHRONOUS IDLE}' \ + || U'\u0017' != U'\N{END OF TRANSMISSION BLOCK}' \ + || U'\u0018' != U'\N{CANCEL}' \ + || U'\u0019' != U'\N{END OF MEDIUM}' \ + || U'\u001A' != U'\N{SUBSTITUTE}' \ + || U'\u001B' != U'\N{ESCAPE}' \ + || U'\u001C' != U'\N{INFORMATION SEPARATOR FOUR}' \ + || U'\u001C' != U'\N{FILE SEPARATOR}' \ + || U'\u001D' != U'\N{INFORMATION SEPARATOR THREE}' \ + || U'\u001D' != U'\N{GROUP SEPARATOR}' \ + || U'\u001E' != U'\N{INFORMATION SEPARATOR TWO}' \ + || U'\u001E' != U'\N{RECORD SEPARATOR}' \ + || U'\u001F' != U'\N{INFORMATION SEPARATOR ONE}' \ + || U'\u001F' != U'\N{UNIT SEPARATOR}' \ + || U'\u007F' != U'\N{DELETE}' \ + || U'\u0082' != U'\N{BREAK PERMITTED HERE}' \ + || U'\u0083' != U'\N{NO BREAK HERE}' \ + || U'\u0084' != U'\N{INDEX}' \ + || U'\u0085' != U'\N{NEXT LINE}' \ + || U'\u0086' != U'\N{START OF SELECTED AREA}' \ + || U'\u0087' != U'\N{END OF SELECTED AREA}' \ + || U'\u0088' != U'\N{CHARACTER TABULATION SET}' \ + || U'\u0088' != U'\N{HORIZONTAL TABULATION SET}' \ + || U'\u0089' != U'\N{CHARACTER TABULATION WITH JUSTIFICATION}' \ + || U'\u0089' != U'\N{HORIZONTAL TABULATION WITH JUSTIFICATION}' \ + || U'\u008A' != U'\N{LINE TABULATION SET}' \ + || U'\u008A' != U'\N{VERTICAL TABULATION SET}' \ + || U'\u008B' != U'\N{PARTIAL LINE FORWARD}' \ + || U'\u008B' != U'\N{PARTIAL LINE DOWN}' \ + || U'\u008C' != U'\N{PARTIAL LINE BACKWARD}' \ + || U'\u008C' != U'\N{PARTIAL LINE UP}' \ + || U'\u008D' != U'\N{REVERSE LINE FEED}' \ + || U'\u008D' != U'\N{REVERSE INDEX}' \ + || U'\u008E' != U'\N{SINGLE SHIFT TWO}' \ + || U'\u008E' != U'\N{SINGLE-SHIFT-2}' \ + || U'\u008F' != U'\N{SINGLE SHIFT THREE}' \ + || U'\u008F' != U'\N{SINGLE-SHIFT-3}' \ + || U'\u0090' != U'\N{DEVICE CONTROL STRING}' \ + || U'\u0091' != U'\N{PRIVATE USE ONE}' \ + || U'\u0091' != U'\N{PRIVATE USE-1}' \ + || U'\u0092' != U'\N{PRIVATE USE TWO}' \ + || U'\u0092' != U'\N{PRIVATE USE-2}' \ + || U'\u0093' != U'\N{SET TRANSMIT STATE}' \ + || U'\u0094' != U'\N{CANCEL CHARACTER}' \ + || U'\u0095' != U'\N{MESSAGE WAITING}' \ + || U'\u0096' != U'\N{START OF GUARDED AREA}' \ + || U'\u0096' != U'\N{START OF PROTECTED AREA}' \ + || U'\u0097' != U'\N{END OF GUARDED AREA}' \ + || U'\u0097' != U'\N{END OF PROTECTED AREA}' \ + || U'\u0098' != U'\N{START OF STRING}' \ + || U'\u009A' != U'\N{SINGLE CHARACTER INTRODUCER}' \ + || U'\u009B' != U'\N{CONTROL SEQUENCE INTRODUCER}' \ + || U'\u009C' != U'\N{STRING TERMINATOR}' \ + || U'\u009D' != U'\N{OPERATING SYSTEM COMMAND}' \ + || U'\u009E' != U'\N{PRIVACY MESSAGE}' \ + || U'\u009F' != U'\N{APPLICATION PROGRAM COMMAND}' \ + || U'\u0020' != U'\N{SPACE}' \ + || U'\u0030' != U'\N{DIGIT ZERO}' \ + || U'\u0053' != U'\N{LATIN CAPITAL LETTER S}' +#error Bad +#endif +#endif +#if U'\U0001F402' != U'\N{OX}' \ + || U'\U0001FBA9' != U'\N{BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT AND MIDDLE LEFT TO LOWER CENTRE}' \ + || U'\u01FD' != U'\N{LATIN SMALL LETTER AE WITH ACUTE}' \ + || U'\u2118' != U'\N{WEIERSTRASS ELLIPTIC FUNCTION}' \ + || U'\u2118' != U'\N{SCRIPT CAPITAL P}' \ + || U'\uFEFF' != U'\N{BYTE ORDER MARK}' \ + || U'\uFEFF' != U'\N{ZERO WIDTH NO-BREAK SPACE}' \ + || U'\u116C' != U'\N{HANGUL JUNGSEONG OE}' \ + || U'\u1180' != U'\N{HANGUL JUNGSEONG O-E}' \ + || U'\u0F60' != U'\N{TIBETAN LETTER -A}' \ + || U'\u0F68' != U'\N{TIBETAN LETTER A}' \ + || U'\u0F0A' != U'\N{TIBETAN MARK BKA- SHOG YIG MGO}' \ + || U'\u0FD0' != U'\N{TIBETAN MARK BKA- SHOG GI MGO RGYAN}' \ + || U'\u0FD0' != U'\N{TIBETAN MARK BSKA- SHOG GI MGO RGYAN}' \ + || U'\uFE18' != U'\N{PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET}' \ + || U'\uFE18' != U'\N{PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRACKET}' \ + || U'\uAC00' != U'\N{HANGUL SYLLABLE GA}' \ + || U'\uAC02' != U'\N{HANGUL SYLLABLE GAGG}' \ + || U'\uAD8D' != U'\N{HANGUL SYLLABLE GWEONJ}' \ + || U'\uAE4D' != U'\N{HANGUL SYLLABLE GGAG}' \ + || U'\uAE4E' != U'\N{HANGUL SYLLABLE GGAGG}' \ + || U'\uC544' != U'\N{HANGUL SYLLABLE A}' \ + || U'\uC55F' != U'\N{HANGUL SYLLABLE AH}' \ + || U'\uC560' != U'\N{HANGUL SYLLABLE AE}' \ + || U'\uD7A3' != U'\N{HANGUL SYLLABLE HIH}' \ + || U'\u3400' != U'\N{CJK UNIFIED IDEOGRAPH-3400}' \ + || U'\u4DBF' != U'\N{CJK UNIFIED IDEOGRAPH-4DBF}' \ + || U'\u4E00' != U'\N{CJK UNIFIED IDEOGRAPH-4E00}' \ + || U'\u9FFC' != U'\N{CJK UNIFIED IDEOGRAPH-9FFC}' \ + || U'\U00020000' != U'\N{CJK UNIFIED IDEOGRAPH-20000}' \ + || U'\U0002A6DD' != U'\N{CJK UNIFIED IDEOGRAPH-2A6DD}' \ + || U'\U00020700' != U'\N{CJK UNIFIED IDEOGRAPH-20700}' \ + || U'\U0002B734' != U'\N{CJK UNIFIED IDEOGRAPH-2B734}' \ + || U'\U0002B740' != U'\N{CJK UNIFIED IDEOGRAPH-2B740}' \ + || U'\U0002B81D' != U'\N{CJK UNIFIED IDEOGRAPH-2B81D}' \ + || U'\U0002B820' != U'\N{CJK UNIFIED IDEOGRAPH-2B820}' \ + || U'\U0002CEA1' != U'\N{CJK UNIFIED IDEOGRAPH-2CEA1}' \ + || U'\U0002CEB0' != U'\N{CJK UNIFIED IDEOGRAPH-2CEB0}' \ + || U'\U0002EBE0' != U'\N{CJK UNIFIED IDEOGRAPH-2EBE0}' \ + || U'\U00030000' != U'\N{CJK UNIFIED IDEOGRAPH-30000}' \ + || U'\U0003134A' != U'\N{CJK UNIFIED IDEOGRAPH-3134A}' \ + || U'\U00017000' != U'\N{TANGUT IDEOGRAPH-17000}' \ + || U'\U000187F7' != U'\N{TANGUT IDEOGRAPH-187F7}' \ + || U'\U00018D00' != U'\N{TANGUT IDEOGRAPH-18D00}' \ + || U'\U00018D08' != U'\N{TANGUT IDEOGRAPH-18D08}' \ + || U'\U00018B00' != U'\N{KHITAN SMALL SCRIPT CHARACTER-18B00}' \ + || U'\U00018CD5' != U'\N{KHITAN SMALL SCRIPT CHARACTER-18CD5}' \ + || U'\U0001B170' != U'\N{NUSHU CHARACTER-1B170}' \ + || U'\U0001B2FB' != U'\N{NUSHU CHARACTER-1B2FB}' \ + || U'\uF900' != U'\N{CJK COMPATIBILITY IDEOGRAPH-F900}' \ + || U'\uFA6D' != U'\N{CJK COMPATIBILITY IDEOGRAPH-FA6D}' \ + || U'\uFA70' != U'\N{CJK COMPATIBILITY IDEOGRAPH-FA70}' \ + || U'\uFAD9' != U'\N{CJK COMPATIBILITY IDEOGRAPH-FAD9}' \ + || U'\U0002F800' != U'\N{CJK COMPATIBILITY IDEOGRAPH-2F800}' \ + || U'\U0002FA1D' != U'\N{CJK COMPATIBILITY IDEOGRAPH-2FA1D}' +#error Bad +#endif + +const char32_t *a = U"\N{HEBREW LETTER KAF}\N{HEBREW LETTER FINAL NUN}"; +const char32_t *b = U"\N{OX}\N{BOX DRAWINGS LIGHT DIAGONAL UPPER CENTRE TO MIDDLE RIGHT AND MIDDLE LEFT TO LOWER CENTRE}"; + +#define b\N{LATIN SMALL LETTER O WITH ACUTE}x U'\U0001FBA9' + +int +main () +{ + if (a[0] != U'\u05DB' || a[1] != U'\U000005DF' || a[2] + || b[0] != U'\U0001F402' || b[1] != b\u{f3}x || b[2]) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-2.c b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-2.c new file mode 100644 index 0000000..4b1af84 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-2.c @@ -0,0 +1,18 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat" { target c } } */ +/* { dg-options "-std=c++23" { target c++ } } */ + +int jalape\N{LATIN SMALL LETTER N WITH TILDE}o = 42; + +int +caf\N{LATIN SMALL LETTER E WITH ACUTE} (void) +{ + return jalape\u00F1o; +} + +int +test (void) +{ + return caf\u00e9 (); +} diff --git a/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-3.c b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-3.c new file mode 100644 index 0000000..5985c03 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-3.c @@ -0,0 +1,22 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do compile } */ +/* { dg-require-effective-target wchar } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat" { target c } } */ +/* { dg-options "-std=c++23" { target c++ } } */ + +#ifndef __cplusplus +typedef __CHAR32_TYPE__ char32_t; +#endif + +const char32_t *a = U"\N{}"; /* { dg-error "empty named universal character escape sequence" } */ +const char32_t *b = U"\N{NU" "LL}"; /* { dg-error "'\\\\N\\{' not terminated with '\\}' after" } */ + /* { dg-error "is not a valid universal character" "" { target c } .-1 } */ +const char32_t *c = U"\N{ I've just made it up }"; /* { dg-error "'\\\\N\\{' not terminated with '\\}' after" } */ + /* { dg-error "is not a valid universal character" "" { target c } .-1 } */ +const char32_t *d = U"\N{_________ _______}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *e = U"\N{O.X}"; /* { dg-error "'\\\\N\\{' not terminated with '\\}' after" } */ + /* { dg-error "is not a valid universal character" "" { target c } .-1 } */ +const char32_t *f = U"\N{.}"; /* { dg-error "'\\\\N\\{' not terminated with '\\}' after" } */ + /* { dg-error "is not a valid universal character" "" { target c } .-1 } */ +const char32_t *g = U"\N{BOM}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *h = U"\N{ZWNBSP}"; /* { dg-error "is not a valid universal character" } */ diff --git a/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-4.c b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-4.c new file mode 100644 index 0000000..75fdeff --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/named-universal-char-escape-4.c @@ -0,0 +1,60 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do compile } */ +/* { dg-require-effective-target wchar } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat" { target c } } */ +/* { dg-options "-std=c++23" { target c++ } } */ + +#ifndef __cplusplus +typedef __CHAR32_TYPE__ char32_t; +#endif + +const char32_t *a = U"\N{ZERO WIDTH NO BREAK SPACE}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{ZERO WIDTH NO-BREAK SPACE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *b = U"\N{giraffe face}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{GIRAFFE FACE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *c = U"\N{Giraffe Face}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{GIRAFFE FACE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *d = U"\N{ GiRaFfE_fAcE__ ___}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{GIRAFFE FACE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *e = U"\N{GIRAFFE}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *f = U"\N{Hangul_Syllable_gAgg_}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL SYLLABLE GAGG\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *g = U"\N{HANGUL SYLLABLE gagg}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL SYLLABLE GAGG\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *h = U"\N{HANGULSYLLABLEGAGG}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL SYLLABLE GAGG\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *i = U"\N{HANGUL_SYLLABLE_GAGG}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL SYLLABLE GAGG\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *j = U"\N{HANGUL SYLLABLE }"; /* { dg-error "is not a valid universal character" } */ +const char32_t *k = U"\N{CJK-COMPATIBILITY-IDEOGRAPH-2F801}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{CJK COMPATIBILITY IDEOGRAPH-2F801\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *l = U"\N{CjK_COMPATIBILITY IDEOGRAPH 2f801}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{CJK COMPATIBILITY IDEOGRAPH-2F801\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *m = U"\N{CjK_COMPATIBILITY IDEOGRAPH 2f80}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *n = U"\N{CJK COMPATIBILITY IDEOGRAPH-}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *o = U"\N{CJK COMPATIBILITY IDEOGRAPH-X}"; /* { dg-error "is not a valid universal character" } */ +const char32_t *p = U"\N{Tibetan Letter A}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{TIBETAN LETTER A\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *q = U"\N{Tibetan LetterA}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{TIBETAN LETTER A\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *r = U"\N{Tibetan Letter-A}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{TIBETAN LETTER A\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *s = U"\N{Tibetan Letter -A}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{TIBETAN LETTER -A\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *t = U"\N{TibetanLetter -A}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{TIBETAN LETTER -A\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *u = U"\N{Hangul Jungseong oe}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG OE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *v = U"\N{Hangul Jungseong o- e}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG O-E\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *w = U"\N{HangulJungseongo-e}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG O-E\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *x = U"\N{Hangul Jungseong oe __ }"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG OE\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *y = U"\N{Hangul Jungseong o- e __ }"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG O-E\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *z = U"\N{Hangul Jungseong o -e}"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG O-E\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *A = U"\N{Hangul Jungseong o -e __ }"; /* { dg-error "is not a valid universal character" } */ + /* { dg-message "did you mean \\\\N\\{HANGUL JUNGSEONG O-E\\}\\?" "" { target *-*-* } .-1 } */ +const char32_t *B = U"\N{O}"; /* { dg-error "is not a valid universal character" } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-kernels-parloops.c b/gcc/testsuite/c-c++-common/goacc/classify-kernels-parloops.c index 5f470eb..fc2b637 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-kernels-parloops.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-kernels-parloops.c @@ -27,16 +27,16 @@ void KERNELS () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check that exactly one OpenACC kernels construct is analyzed, and that it can be parallelized. { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is parallelized OpenACC kernels offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized-parloops.c b/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized-parloops.c index 06c70fb..08e69c4 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized-parloops.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized-parloops.c @@ -31,16 +31,16 @@ void KERNELS () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check that exactly one OpenACC kernels construct is analyzed, and that it can't be parallelized. { dg-final { scan-tree-dump-times "FAILED:" 1 "parloops1" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } { dg-final { scan-tree-dump-not "SUCCESS: may be parallelized" "parloops1" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is unparallelized OpenACC kernels offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized.c b/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized.c index 61871d1..ce38079 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-kernels-unparallelized.c @@ -40,16 +40,16 @@ void KERNELS () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check that exactly one OpenACC kernels construct is analyzed, and that it can't be parallelized. { dg-final { scan-tree-dump-times "FAILED:" 1 "parloops1" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } { dg-final { scan-tree-dump-not "SUCCESS: may be parallelized" "parloops1" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is unparallelized OpenACC kernels offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-kernels.c b/gcc/testsuite/c-c++-common/goacc/classify-kernels.c index 1473337..31c1200 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-kernels.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-kernels.c @@ -36,16 +36,16 @@ void KERNELS () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check that exactly one OpenACC kernels construct is analyzed, and that it can be parallelized. { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is parallelized OpenACC kernels offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-parallel.c b/gcc/testsuite/c-c++-common/goacc/classify-parallel.c index 61d03c0..19101fa 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-parallel.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-parallel.c @@ -24,10 +24,10 @@ void PARALLEL () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is OpenACC parallel offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/classify-serial.c b/gcc/testsuite/c-c++-common/goacc/classify-serial.c index 71b8c72..6480fe3 100644 --- a/gcc/testsuite/c-c++-common/goacc/classify-serial.c +++ b/gcc/testsuite/c-c++-common/goacc/classify-serial.c @@ -29,10 +29,10 @@ void SERIAL () } /* Check the offloaded function's attributes. - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint\\)\\)" 1 "ompexp" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } */ /* Check the offloaded function's classification and compute dimensions (will always be 1 x 1 x 1 for non-offloading compilation). { dg-final { scan-tree-dump-times "(?n)Function is OpenACC serial offload" 1 "oaccloops" } } { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } - { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint\\)\\)" 1 "oaccloops" } } */ + { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-counter-vars-function-scope.c b/gcc/testsuite/c-c++-common/goacc/kernels-counter-vars-function-scope.c index c475333..bce17a1 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-counter-vars-function-scope.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-counter-vars-function-scope.c @@ -45,7 +45,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-2.c index acef6a1..456a954 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-2.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-2.c @@ -59,7 +59,7 @@ main (void) /* Check that only three loops are analyzed, and that all can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-3.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-3.c index 75e2bb7..ef0c481 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-3.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-3.c @@ -39,7 +39,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-2.c index 7180021..a640078 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-2.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-2.c @@ -59,7 +59,7 @@ main (void) /* Check that only three loops are analyzed, and that all can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit-2.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit-2.c index 0c9f833..d46bba8 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit-2.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit-2.c @@ -57,7 +57,7 @@ main (void) /* Check that only three loops are analyzed, and that all can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit.c index 0bd21b6..6698980 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-enter-exit.c @@ -54,7 +54,7 @@ main (void) /* Check that only three loops are analyzed, and that all can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-update.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-update.c index dd5a841..9c6997f 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-update.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data-update.c @@ -55,7 +55,7 @@ main (void) /* Check that only two loops are analyzed, and that both can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 2 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 2 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data.c index a658182..0ef5765 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-data.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-data.c @@ -53,7 +53,7 @@ main (void) /* Check that only three loops are analyzed, and that all can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-g.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-g.c index 5bdaa40..cf9f1ee 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-g.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-g.c @@ -10,7 +10,7 @@ /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-mod-not-zero.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-mod-not-zero.c index 5592623..eea9a73 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-mod-not-zero.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-mod-not-zero.c @@ -43,7 +43,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-n.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-n.c index e86be1b..a63ed8a 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-n.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-n.c @@ -46,7 +46,7 @@ foo (COUNTERTYPE n) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop-nest.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop-nest.c index 2b0e186..b3bb5ca 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop-nest.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop-nest.c @@ -30,7 +30,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-loop.c b/gcc/testsuite/c-c++-common/goacc/kernels-loop.c index 9619d53..2602081 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-loop.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-loop.c @@ -46,7 +46,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-one-counter-var.c b/gcc/testsuite/c-c++-common/goacc/kernels-one-counter-var.c index 69539b2..0d9c875 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-one-counter-var.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-one-counter-var.c @@ -44,7 +44,7 @@ main (void) /* Check that only one loop is analyzed, and that it can be parallelized. */ /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/goacc/kernels-parallel-loop-data-enter-exit.c b/gcc/testsuite/c-c++-common/goacc/kernels-parallel-loop-data-enter-exit.c index 81b0fee..1dcd32f 100644 --- a/gcc/testsuite/c-c++-common/goacc/kernels-parallel-loop-data-enter-exit.c +++ b/gcc/testsuite/c-c++-common/goacc/kernels-parallel-loop-data-enter-exit.c @@ -57,7 +57,7 @@ main (void) // FIXME: OpenACC kernels stopped working with the firstprivate subarray // changes. /* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops1" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 2 "parloops1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 2 "parloops1" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-not "FAILED:" "parloops1" { xfail *-*-* } } } */ /* Check that the loop has been split off into a function. */ diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-2.c b/gcc/testsuite/c-c++-common/gomp/doacross-2.c index cc45487..44c5c21 100644 --- a/gcc/testsuite/c-c++-common/gomp/doacross-2.c +++ b/gcc/testsuite/c-c++-common/gomp/doacross-2.c @@ -7,13 +7,13 @@ foo (void) #pragma omp for ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */ + #pragma omp ordered ; } #pragma omp for ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered threads /* { dg-error "'ordered' region without 'depend' clause may not be closely nested inside a loop region with an 'ordered' clause with a parameter" } */ + #pragma omp ordered threads ; } } @@ -25,14 +25,20 @@ bar (void) #pragma omp for ordered for (i = 0; i < 64; i++) { - #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ + #pragma omp ordered depend(source) + #pragma omp ordered depend(sink: i - 1) + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 1) } #pragma omp for for (i = 0; i < 64; i++) { - #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered' construct with 'depend' clause must be closely nested inside a loop with 'ordered' clause" } */ } #pragma omp for for (i = 0; i < 64; i++) diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-5.c b/gcc/testsuite/c-c++-common/gomp/doacross-5.c new file mode 100644 index 0000000..9dd6dbf4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/doacross-5.c @@ -0,0 +1,94 @@ +void +foo (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 2) + } +} + +void +bar (int n) +{ + int i, j; + #pragma omp for collapse(2) ordered(2) + for (i = 0; i < 8; i += n) + for (j = 0; j < 8; j += n) + { + #pragma omp ordered doacross(source:omp_cur_iteration) + #pragma omp ordered doacross(sink: i - 2, j + 2) + } +} + +void +baz (void) +{ + int i, j; + #pragma omp for ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */ + ; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink: i - 1) + } + #pragma omp for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(source: omp_cur_iteration ) + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses must not have the same binding region as 'ordered' construct with those clauses" } */ + ; + } + #pragma omp for ordered(2) + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + { + #pragma omp ordered /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */ + ; + } + #pragma omp for ordered(2) collapse(1) + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + { + #pragma omp ordered threads /* { dg-error "'ordered' construct without 'doacross' or 'depend' clauses binds to loop where 'collapse' argument 1 is different from 'ordered' argument 2" } */ + ; + } +} + +void +qux (void) +{ + int i, j = 0; + #pragma omp for ordered linear(j) + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered + ; + } + #pragma omp for ordered linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */ + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink:i-1) + } + #pragma omp for ordered(1) linear(j) + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered + ; + } + #pragma omp for ordered(1) linear(j) /* { dg-error "'linear' clause may not be specified together with 'ordered' clause if stand-alone 'ordered' construct is nested in it" } */ + for (i = 0; i < 64; i++) + { + ++j; + #pragma omp ordered doacross(source:) + #pragma omp ordered doacross(sink:i-1) + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-6.c b/gcc/testsuite/c-c++-common/gomp/doacross-6.c new file mode 100644 index 0000000..d126ad1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/doacross-6.c @@ -0,0 +1,74 @@ +void +foo (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source) /* { dg-error "expected ':' before '\\\)' token" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:omp_current_iteration) /* { dg-error "expected '\\\)' before 'omp_current_iteration'" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(source:i - 2) /* { dg-error "expected '\\\)' before 'i'" } */ + } + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink) /* { dg-error "expected ':' before '\\\)' token" } */ + } +} + +void +bar (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_current_iteration - 1) /* { dg-error "'omp_current_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_current_iteration' has not been declared" "" { target c++ } .-1 } */ + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} + +void +baz (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration + 1) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} + +void +qux (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration - (2 - 1)) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "expected integer before '\\\(' token" "" { target *-*-* } .-1 } */ +} /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-2 } */ + /* { dg-error "expected '\\\)' before '\\\(' token" "" { target c++ } .-3 } */ +void +corge (int n) +{ + int i; + #pragma omp for ordered + for (i = 0; i < 8; i += n) + { + #pragma omp ordered doacross(sink:omp_cur_iteration - 1LL) /* { dg-error "'omp_cur_iteration' undeclared \\\(first use in this function\\\)" "" { target c } } */ + } /* { dg-error "'omp_cur_iteration' has not been declared" "" { target c++ } .-1 } */ +} diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-2.c b/gcc/testsuite/c-c++-common/gomp/nesting-2.c index 420cfd3..6ce560d 100644 --- a/gcc/testsuite/c-c++-common/gomp/nesting-2.c +++ b/gcc/testsuite/c-c++-common/gomp/nesting-2.c @@ -160,7 +160,14 @@ foo (void) for (i = 0; i < 64; i++) #pragma omp parallel { - #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp for ordered(1) + for (i = 0; i < 64; i++) + #pragma omp parallel + { + #pragma omp ordered doacross(source:) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error ".ordered. construct with .doacross. clause must be closely nested inside a loop with .ordered. clause" } */ } } diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-3.c b/gcc/testsuite/c-c++-common/gomp/ordered-3.c index e7fd738..b007ca7 100644 --- a/gcc/testsuite/c-c++-common/gomp/ordered-3.c +++ b/gcc/testsuite/c-c++-common/gomp/ordered-3.c @@ -47,29 +47,53 @@ foo (void) #pragma omp ordered threads, simd, threads, simd /* { dg-error "too many .threads. clauses" } */ ; /* { dg-error "too many .simd. clauses" "" { target *-*-* } .-1 } */ } - #pragma omp for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp for simd. construct" } */ + #pragma omp for simd ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } - #pragma omp parallel for simd ordered(1) /* { dg-error ".ordered. clause with parameter may not be specified on .#pragma omp parallel for simd. construct" } */ + #pragma omp for simd ordered(1) for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:omp_cur_iteration) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for simd ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for simd ordered(1) + for (i = 0; i < 64; i++) + { + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + } + #pragma omp parallel for ordered + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) + #pragma omp ordered depend(source) } #pragma omp parallel for ordered for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) + #pragma omp ordered doacross(source:) + } + #pragma omp parallel for + for (i = 0; i < 64; i++) + { + #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } #pragma omp parallel for for (i = 0; i < 64; i++) { - #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ - #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */ + #pragma omp ordered doacross(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ + #pragma omp ordered doacross(source:) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause" } */ } } diff --git a/gcc/testsuite/c-c++-common/gomp/reverse-offload-1.c b/gcc/testsuite/c-c++-common/gomp/reverse-offload-1.c index 3452156..9a3fa52 100644 --- a/gcc/testsuite/c-c++-common/gomp/reverse-offload-1.c +++ b/gcc/testsuite/c-c++-common/gomp/reverse-offload-1.c @@ -43,7 +43,7 @@ tg_fn (int *x, int *y) x2 = x2 + 2 + called_in_target1 (); y2 = y2 + 7; - #pragma omp target device(ancestor : 1) map(tofrom: x2) /* { dg-message "sorry, unimplemented: 'ancestor' not yet supported" } */ + #pragma omp target device(ancestor : 1) map(tofrom: x2) check_offload(&x2, &y2); if (x2 != 2+2+3+42 || y2 != 3 + 7) diff --git a/gcc/testsuite/c-c++-common/gomp/sink-3.c b/gcc/testsuite/c-c++-common/gomp/sink-3.c index 588aea2..3f7ba5e 100644 --- a/gcc/testsuite/c-c++-common/gomp/sink-3.c +++ b/gcc/testsuite/c-c++-common/gomp/sink-3.c @@ -14,7 +14,7 @@ foo () for (i=0; i < 100; ++i) { #pragma omp ordered depend(sink:poo-1,paa+1) /* { dg-error "poo.*declared.*paa.*declared" } */ - bar(&i); /* { dg-error "may not be closely nested" "" { target *-*-* } .-1 } */ + bar(&i); /* { dg-error "must not have the same binding region" "" { target *-*-* } .-1 } */ #pragma omp ordered depend(source) } } diff --git a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c index 241234f..87ac754 100644 --- a/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c +++ b/gcc/testsuite/c-c++-common/gomp/target-device-ancestor-4.c @@ -9,7 +9,7 @@ void foo (void) { - #pragma omp target device (ancestor: 1) /* { dg-message "sorry, unimplemented: 'ancestor' not yet supported" } */ + #pragma omp target device (ancestor: 1) ; } diff --git a/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-1.C b/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-1.C new file mode 100644 index 0000000..d33fd53 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-1.C @@ -0,0 +1,6 @@ +// P2071R2 - Named universal character escapes +// { dg-do compile { target c++11 } } +// { dg-require-effective-target wchar } +// { dg-options "-pedantic" } + +const char32_t *a = U"\N{ETHIOPIC SYLLABLE SEE}"; // { dg-warning "named universal character escapes are only valid in" "" { target c++20_down } } diff --git a/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-2.C b/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-2.C new file mode 100644 index 0000000..b98a29d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/named-universal-char-escape-2.C @@ -0,0 +1,6 @@ +// P2071R2 - Named universal character escapes +// { dg-do compile { target c++11 } } +// { dg-require-effective-target wchar } +// { dg-options "-pedantic-errors" } + +const char32_t *a = U"\N{ETHIOPIC SYLLABLE SEE}"; // { dg-error "named universal character escapes are only valid in" "" { target c++20_down } } diff --git a/gcc/testsuite/g++.dg/cpp/warning-1.C b/gcc/testsuite/g++.dg/cpp/warning-1.C new file mode 100644 index 0000000..2d857cf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/warning-1.C @@ -0,0 +1,6 @@ +// P2437R1 - Support for #warning +// { dg-do preprocess } +// { dg-options "-pedantic-errors" } + +#warning example text /* { dg-warning "example text" } */ +// { dg-error "#warning before C\\\+\\\+23 is a GCC extension" "pedantic" { target c++20_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp/warning-2.C b/gcc/testsuite/g++.dg/cpp/warning-2.C new file mode 100644 index 0000000..d6d5d9f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/warning-2.C @@ -0,0 +1,6 @@ +// P2437R1 - Support for #warning +// { dg-do preprocess } +// { dg-options "-pedantic" } + +#warning example text /* { dg-warning "example text" } */ +// { dg-warning "#warning before C\\\+\\\+23 is a GCC extension" "pedantic" { target c++20_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp/warning-3.C b/gcc/testsuite/g++.dg/cpp/warning-3.C new file mode 100644 index 0000000..1595b4d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/warning-3.C @@ -0,0 +1,6 @@ +// P2437R1 - Support for #warning +// { dg-do preprocess } +// { dg-options "" } + +#warning example text /* { dg-warning "example text" } */ +// { dg-bogus "#warning before C\\\+\\\+23 is a GCC extension" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C deleted file mode 100644 index 8464aa3..0000000 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C +++ /dev/null @@ -1,12 +0,0 @@ -// Origin: PR c++/51032 -// { dg-do compile { target { c++11 && stabs } } } -// { dg-options "-gstabs+" } - -template <class C> -struct A { - template<class U> using B = U*; - int a; -}; - -A<int> a; - diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-77.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-77.C new file mode 100644 index 0000000..2c41c62 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-77.C @@ -0,0 +1,17 @@ +// PR c++/106712 +// { dg-do compile { target c++11 } } + +[[noreturn]] int f1 [[nodiscard]](), f2 (); +[[nodiscard]] int f3 (), f4 (); +int f5 [[nodiscard]](), f6 (); + +int +main () +{ + f1 (); // { dg-warning "ignoring" } + f2 (); + f3 (); // { dg-warning "ignoring" } + f4 (); // { dg-warning "ignoring" } + f5 (); // { dg-warning "ignoring" } + f6 (); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv.C index 417c185..9f1b89aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv.C @@ -1,7 +1,7 @@ // Test for conversion from stateless lambda to function pointer. // { dg-do compile { target c++11_only } } -// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1fvENKUlvE_cvPFvvEEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin *-*-hpux10* } } } } } +// { dg-final { scan-assembler "weak\[^\n\r\]*_?_ZZ1fvENKUlvE_cvPFvvEEv" { target { ! { *-*-darwin* *-*-mingw* *-*-cygwin } } } } } inline void f() { diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-1.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-1.C new file mode 100644 index 0000000..95e3827 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-1.C @@ -0,0 +1,43 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8" } + +// aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } +// a€a { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +// a¿a { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +// aÀa { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +// aÁa { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +// aõa { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +// aÿa { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +// aÂa { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +// aàa { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +// aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +// aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +// aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +// aì€a { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +// aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +// að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +// að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +// aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +// aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } +// { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +/* aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } */ +/* a€a { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } */ +/* a¿a { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } */ +/* aÀa { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } */ +/* aÁa { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } */ +/* aõa { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } */ +/* aÿa { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } */ +/* aÂa { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } */ +/* aàa { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } */ +/* aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } */ +/* aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } */ +/* aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } */ +/* aì€a { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } */ +/* aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } */ +/* að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } */ +/* að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } */ +/* aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } */ +/* aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } */ +/* { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } */ diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-10.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-10.C new file mode 100644 index 0000000..4684b9d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-10.C @@ -0,0 +1,25 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic" } + +#define I(x) +I(Â€ß¿à €íŸ¿î€€ð€€ô¿¿) // { dg-bogus "invalid UTF-8 character" } + // { dg-error "is not valid in an identifier" "" { target *-*-* } .-1 } +I(€) // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +I(¿) // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +I(À) // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +I(Á) // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +I(õ) // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +I(ÿ) // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +I(Â) // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +I(à) // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +I(à€¿) // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +I(àŸ€) // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +I(à¿) // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +I(ì€) // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +I(í €) // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +I(ð€€€) // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +I(ð¿¿) // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +I(ô€€) // { dg-error "is not valid in an identifier" } +I(ý¿¿¿¿¿) // { dg-error "is not valid in an identifier" } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-11.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-11.C new file mode 100644 index 0000000..85f04bf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-11.C @@ -0,0 +1,25 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors" } + +#define I(x) +I(Â€ß¿à €íŸ¿î€€ð€€ô¿¿) // { dg-bogus "invalid UTF-8 character" } + // { dg-error "is not valid in an identifier" "" { target *-*-* } .-1 } +I(€) // { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +I(¿) // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +I(À) // { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +I(Á) // { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +I(õ) // { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +I(ÿ) // { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +I(Â) // { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +I(à) // { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +I(à€¿) // { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +I(àŸ€) // { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +I(à¿) // { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +I(ì€) // { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +I(í €) // { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +I(ð€€€) // { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +I(ð¿¿) // { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +I(ô€€) // { dg-error "is not valid in an identifier" } +I(ý¿¿¿¿¿) // { dg-error "is not valid in an identifier" } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-12.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-12.C new file mode 100644 index 0000000..6a4091f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-12.C @@ -0,0 +1,25 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors -Wno-invalid-utf8" } + +#define I(x) +I(Â€ß¿à €íŸ¿î€€ð€€ô¿¿) // { dg-bogus "invalid UTF-8 character" } + // { dg-error "is not valid in an identifier" "" { target *-*-* } .-1 } +I(€) // { dg-bogus "invalid UTF-8 character <80>" } +I(¿) // { dg-bogus "invalid UTF-8 character <bf>" } +I(À) // { dg-bogus "invalid UTF-8 character <c0>" } +I(Á) // { dg-bogus "invalid UTF-8 character <c1>" } +I(õ) // { dg-bogus "invalid UTF-8 character <f5>" } +I(ÿ) // { dg-bogus "invalid UTF-8 character <ff>" } +I(Â) // { dg-bogus "invalid UTF-8 character <c2>" } +I(à) // { dg-bogus "invalid UTF-8 character <e0>" } +I(à€¿) // { dg-bogus "invalid UTF-8 character <e0><80><bf>" } +I(àŸ€) // { dg-bogus "invalid UTF-8 character <e0><9f><80>" } +I(à¿) // { dg-bogus "invalid UTF-8 character <e0><bf>" } +I(ì€) // { dg-bogus "invalid UTF-8 character <ec><80>" } +I(í €) // { dg-bogus "invalid UTF-8 character <ed><a0><80>" } +I(ð€€€) // { dg-bogus "invalid UTF-8 character <f0><80><80><80>" } +I(ð¿¿) // { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" } +I(ô€€) // { dg-error "is not valid in an identifier" } +I(ý¿¿¿¿¿) // { dg-error "is not valid in an identifier" } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-2.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-2.C new file mode 100644 index 0000000..70ab8e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-2.C @@ -0,0 +1,43 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic" } + +// aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } +// a€a { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +// a¿a { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +// aÀa { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +// aÁa { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +// aõa { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +// aÿa { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +// aÂa { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +// aàa { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +// aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +// aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +// aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +// aì€a { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +// aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +// að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +// að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +// aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +// aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } +// { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +/* aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } */ +/* a€a { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } */ +/* a¿a { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } */ +/* aÀa { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } */ +/* aÁa { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } */ +/* aõa { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } */ +/* aÿa { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } */ +/* aÂa { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } */ +/* aàa { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } */ +/* aà€¿a { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } */ +/* aàŸ€a { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } */ +/* aà¿a { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } */ +/* aì€a { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } */ +/* aí €a { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } */ +/* að€€€a { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } */ +/* að¿¿a { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } */ +/* aô€€a { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } */ +/* aý¿¿¿¿¿a { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } */ +/* { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } */ diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-3.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-3.C new file mode 100644 index 0000000..c0f748b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-3.C @@ -0,0 +1,43 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors" } + +// aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } +// a€a { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +// a¿a { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +// aÀa { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +// aÁa { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +// aõa { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +// aÿa { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +// aÂa { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +// aàa { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +// aà€¿a { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +// aàŸ€a { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +// aà¿a { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +// aì€a { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +// aí €a { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +// að€€€a { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +// að¿¿a { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +// aô€€a { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +// aý¿¿¿¿¿a { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } +// { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +/* aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } */ +/* a€a { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } */ +/* a¿a { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } */ +/* aÀa { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } */ +/* aÁa { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } */ +/* aõa { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } */ +/* aÿa { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } */ +/* aÂa { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } */ +/* aàa { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } */ +/* aà€¿a { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } */ +/* aàŸ€a { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } */ +/* aà¿a { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } */ +/* aì€a { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } */ +/* aí €a { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } */ +/* að€€€a { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } */ +/* að¿¿a { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } */ +/* aô€€a { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } */ +/* aý¿¿¿¿¿a { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } */ +/* { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } */ diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-4.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-4.C new file mode 100644 index 0000000..1dc65e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-4.C @@ -0,0 +1,43 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors -Wno-invalid-utf8" } + +// aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } +// a€a { dg-bogus "invalid UTF-8 character <80>" } +// a¿a { dg-bogus "invalid UTF-8 character <bf>" } +// aÀa { dg-bogus "invalid UTF-8 character <c0>" } +// aÁa { dg-bogus "invalid UTF-8 character <c1>" } +// aõa { dg-bogus "invalid UTF-8 character <f5>" } +// aÿa { dg-bogus "invalid UTF-8 character <ff>" } +// aÂa { dg-bogus "invalid UTF-8 character <c2>" } +// aàa { dg-bogus "invalid UTF-8 character <e0>" } +// aà€¿a { dg-bogus "invalid UTF-8 character <e0><80><bf>" } +// aàŸ€a { dg-bogus "invalid UTF-8 character <e0><9f><80>" } +// aà¿a { dg-bogus "invalid UTF-8 character <e0><bf>" } +// aì€a { dg-bogus "invalid UTF-8 character <ec><80>" } +// aí €a { dg-bogus "invalid UTF-8 character <ed><a0><80>" } +// að€€€a { dg-bogus "invalid UTF-8 character <f0><80><80><80>" } +// að¿¿a { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" } +// aô€€a { dg-bogus "invalid UTF-8 character <f4><90><80><80>" } +// aý¿¿¿¿¿a { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" } +// { dg-bogus "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } +/* aÂ€ß¿à €íŸ¿î€€ð€€ô¿¿a { dg-bogus "invalid UTF-8 character" } */ +/* a€a { dg-bogus "invalid UTF-8 character <80>" } */ +/* a¿a { dg-bogus "invalid UTF-8 character <bf>" } */ +/* aÀa { dg-bogus "invalid UTF-8 character <c0>" } */ +/* aÁa { dg-bogus "invalid UTF-8 character <c1>" } */ +/* aõa { dg-bogus "invalid UTF-8 character <f5>" } */ +/* aÿa { dg-bogus "invalid UTF-8 character <ff>" } */ +/* aÂa { dg-bogus "invalid UTF-8 character <c2>" } */ +/* aàa { dg-bogus "invalid UTF-8 character <e0>" } */ +/* aà€¿a { dg-bogus "invalid UTF-8 character <e0><80><bf>" } */ +/* aàŸ€a { dg-bogus "invalid UTF-8 character <e0><9f><80>" } */ +/* aà¿a { dg-bogus "invalid UTF-8 character <e0><bf>" } */ +/* aì€a { dg-bogus "invalid UTF-8 character <ec><80>" } */ +/* aí €a { dg-bogus "invalid UTF-8 character <ed><a0><80>" } */ +/* að€€€a { dg-bogus "invalid UTF-8 character <f0><80><80><80>" } */ +/* að¿¿a { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" } */ +/* aô€€a { dg-bogus "invalid UTF-8 character <f4><90><80><80>" } */ +/* aý¿¿¿¿¿a { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" } */ +/* { dg-bogus "invalid UTF-8 character <bf>" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-5.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-5.C new file mode 100644 index 0000000..f0140ba --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-5.C @@ -0,0 +1,80 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess { target c++11 } } +// { dg-options "-finput-charset=UTF-8" } + +char32_t a = U'€'; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +char32_t b = U'¿'; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +char32_t c = U'À'; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +char32_t d = U'Á'; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +char32_t e = U'õ'; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +char32_t f = U'ÿ'; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +char32_t g = U'Â'; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +char32_t h = U'à'; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +char32_t i = U'à€¿'; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +char32_t j = U'àŸ€'; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +char32_t k = U'à¿'; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +char32_t l = U'ì€'; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +char32_t m = U'í €'; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +char32_t n = U'ð€€€'; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +char32_t o = U'ð¿¿'; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +char32_t p = U'ô€€'; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +char32_t q = U'ý¿¿¿¿¿'; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A = U"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B = U"€"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C = U"¿"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D = U"À"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E = U"Á"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F = U"õ"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G = U"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H = U"Â"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I = U"à"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J = U"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K = U"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L = U"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M = U"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N = U"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O = U"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P = U"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q = U"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R = U"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A1 = UR"(Â€ß¿à €íŸ¿î€€ð€€ô¿¿)"; // { dg-bogus "invalid UTF-8 character" } +auto B1 = UR"(€)"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C1 = UR"(¿)"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D1 = UR"(À)"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E1 = UR"(Á)"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F1 = UR"(õ)"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G1 = UR"(ÿ)"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H1 = UR"(Â)"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I1 = UR"(à)"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J1 = UR"(à€¿)"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K1 = UR"(àŸ€)"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L1 = UR"(à¿)"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M1 = UR"(ì€)"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N1 = UR"(í €)"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O1 = UR"(ð€€€)"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P1 = UR"(ð¿¿)"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q1 = UR"(ô€€)"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R1 = UR"(ý¿¿¿¿¿)"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A2 = u8"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B2 = u8"€"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C2 = u8"¿"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D2 = u8"À"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E2 = u8"Á"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F2 = u8"õ"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G2 = u8"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H2 = u8"Â"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I2 = u8"à"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J2 = u8"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K2 = u8"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L2 = u8"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M2 = u8"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N2 = u8"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O2 = u8"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P2 = u8"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q2 = u8"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R2 = u8"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-6.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-6.C new file mode 100644 index 0000000..01023d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-6.C @@ -0,0 +1,80 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess { target c++11 } } +// { dg-options "-finput-charset=UTF-8 -pedantic" } + +char32_t a = U'€'; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +char32_t b = U'¿'; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +char32_t c = U'À'; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +char32_t d = U'Á'; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +char32_t e = U'õ'; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +char32_t f = U'ÿ'; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +char32_t g = U'Â'; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +char32_t h = U'à'; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +char32_t i = U'à€¿'; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +char32_t j = U'àŸ€'; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +char32_t k = U'à¿'; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +char32_t l = U'ì€'; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +char32_t m = U'í €'; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +char32_t n = U'ð€€€'; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +char32_t o = U'ð¿¿'; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +char32_t p = U'ô€€'; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +char32_t q = U'ý¿¿¿¿¿'; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A = U"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B = U"€"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C = U"¿"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D = U"À"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E = U"Á"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F = U"õ"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G = U"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H = U"Â"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I = U"à"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J = U"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K = U"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L = U"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M = U"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N = U"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O = U"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P = U"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q = U"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R = U"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A1 = UR"(Â€ß¿à €íŸ¿î€€ð€€ô¿¿)"; // { dg-bogus "invalid UTF-8 character" } +auto B1 = UR"(€)"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C1 = UR"(¿)"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D1 = UR"(À)"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E1 = UR"(Á)"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F1 = UR"(õ)"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G1 = UR"(ÿ)"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H1 = UR"(Â)"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I1 = UR"(à)"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J1 = UR"(à€¿)"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K1 = UR"(àŸ€)"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L1 = UR"(à¿)"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M1 = UR"(ì€)"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N1 = UR"(í €)"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O1 = UR"(ð€€€)"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P1 = UR"(ð¿¿)"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q1 = UR"(ô€€)"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R1 = UR"(ý¿¿¿¿¿)"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A2 = u8"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B2 = u8"€"; // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +auto C2 = u8"¿"; // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D2 = u8"À"; // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E2 = u8"Á"; // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F2 = u8"õ"; // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G2 = u8"ÿ"; // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H2 = u8"Â"; // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I2 = u8"à"; // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J2 = u8"à€¿"; // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K2 = u8"àŸ€"; // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L2 = u8"à¿"; // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M2 = u8"ì€"; // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N2 = u8"í €"; // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O2 = u8"ð€€€"; // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P2 = u8"ð¿¿"; // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q2 = u8"ô€€"; // { dg-warning "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R2 = u8"ý¿¿¿¿¿"; // { dg-warning "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-7.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-7.C new file mode 100644 index 0000000..7991a64 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-7.C @@ -0,0 +1,80 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess { target c++11 } } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors" } + +char32_t a = U'€'; // { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +char32_t b = U'¿'; // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +char32_t c = U'À'; // { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +char32_t d = U'Á'; // { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +char32_t e = U'õ'; // { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +char32_t f = U'ÿ'; // { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +char32_t g = U'Â'; // { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +char32_t h = U'à'; // { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +char32_t i = U'à€¿'; // { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +char32_t j = U'àŸ€'; // { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +char32_t k = U'à¿'; // { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +char32_t l = U'ì€'; // { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +char32_t m = U'í €'; // { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +char32_t n = U'ð€€€'; // { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +char32_t o = U'ð¿¿'; // { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +char32_t p = U'ô€€'; // { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +char32_t q = U'ý¿¿¿¿¿'; // { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A = U"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B = U"€"; // { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +auto C = U"¿"; // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D = U"À"; // { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E = U"Á"; // { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F = U"õ"; // { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G = U"ÿ"; // { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H = U"Â"; // { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I = U"à"; // { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J = U"à€¿"; // { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K = U"àŸ€"; // { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L = U"à¿"; // { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M = U"ì€"; // { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N = U"í €"; // { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O = U"ð€€€"; // { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P = U"ð¿¿"; // { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q = U"ô€€"; // { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R = U"ý¿¿¿¿¿"; // { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A1 = UR"(Â€ß¿à €íŸ¿î€€ð€€ô¿¿)"; // { dg-bogus "invalid UTF-8 character" } +auto B1 = UR"(€)"; // { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +auto C1 = UR"(¿)"; // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D1 = UR"(À)"; // { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E1 = UR"(Á)"; // { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F1 = UR"(õ)"; // { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G1 = UR"(ÿ)"; // { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H1 = UR"(Â)"; // { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I1 = UR"(à)"; // { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J1 = UR"(à€¿)"; // { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K1 = UR"(àŸ€)"; // { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L1 = UR"(à¿)"; // { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M1 = UR"(ì€)"; // { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N1 = UR"(í €)"; // { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O1 = UR"(ð€€€)"; // { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P1 = UR"(ð¿¿)"; // { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q1 = UR"(ô€€)"; // { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R1 = UR"(ý¿¿¿¿¿)"; // { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A2 = u8"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B2 = u8"€"; // { dg-error "invalid UTF-8 character <80>" "" { target c++23 } } +auto C2 = u8"¿"; // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D2 = u8"À"; // { dg-error "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E2 = u8"Á"; // { dg-error "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F2 = u8"õ"; // { dg-error "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G2 = u8"ÿ"; // { dg-error "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H2 = u8"Â"; // { dg-error "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I2 = u8"à"; // { dg-error "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J2 = u8"à€¿"; // { dg-error "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K2 = u8"àŸ€"; // { dg-error "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L2 = u8"à¿"; // { dg-error "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M2 = u8"ì€"; // { dg-error "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N2 = u8"í €"; // { dg-error "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O2 = u8"ð€€€"; // { dg-error "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P2 = u8"ð¿¿"; // { dg-error "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q2 = u8"ô€€"; // { dg-error "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R2 = u8"ý¿¿¿¿¿"; // { dg-error "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-error "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-8.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-8.C new file mode 100644 index 0000000..95c8a91 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-8.C @@ -0,0 +1,80 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess { target c++11 } } +// { dg-options "-finput-charset=UTF-8 -pedantic-errors -Wno-invalid-utf8" } + +char32_t a = U'€'; // { dg-bogus "invalid UTF-8 character <80>" "" { target c++23 } } +char32_t b = U'¿'; // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } } +char32_t c = U'À'; // { dg-bogus "invalid UTF-8 character <c0>" "" { target c++23 } } +char32_t d = U'Á'; // { dg-bogus "invalid UTF-8 character <c1>" "" { target c++23 } } +char32_t e = U'õ'; // { dg-bogus "invalid UTF-8 character <f5>" "" { target c++23 } } +char32_t f = U'ÿ'; // { dg-bogus "invalid UTF-8 character <ff>" "" { target c++23 } } +char32_t g = U'Â'; // { dg-bogus "invalid UTF-8 character <c2>" "" { target c++23 } } +char32_t h = U'à'; // { dg-bogus "invalid UTF-8 character <e0>" "" { target c++23 } } +char32_t i = U'à€¿'; // { dg-bogus "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +char32_t j = U'àŸ€'; // { dg-bogus "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +char32_t k = U'à¿'; // { dg-bogus "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +char32_t l = U'ì€'; // { dg-bogus "invalid UTF-8 character <ec><80>" "" { target c++23 } } +char32_t m = U'í €'; // { dg-bogus "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +char32_t n = U'ð€€€'; // { dg-bogus "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +char32_t o = U'ð¿¿'; // { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +char32_t p = U'ô€€'; // { dg-bogus "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +char32_t q = U'ý¿¿¿¿¿'; // { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A = U"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B = U"€"; // { dg-bogus "invalid UTF-8 character <80>" "" { target c++23 } } +auto C = U"¿"; // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D = U"À"; // { dg-bogus "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E = U"Á"; // { dg-bogus "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F = U"õ"; // { dg-bogus "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G = U"ÿ"; // { dg-bogus "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H = U"Â"; // { dg-bogus "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I = U"à"; // { dg-bogus "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J = U"à€¿"; // { dg-bogus "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K = U"àŸ€"; // { dg-bogus "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L = U"à¿"; // { dg-bogus "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M = U"ì€"; // { dg-bogus "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N = U"í €"; // { dg-bogus "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O = U"ð€€€"; // { dg-bogus "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P = U"ð¿¿"; // { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q = U"ô€€"; // { dg-bogus "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R = U"ý¿¿¿¿¿"; // { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A1 = UR"(Â€ß¿à €íŸ¿î€€ð€€ô¿¿)"; // { dg-bogus "invalid UTF-8 character" } +auto B1 = UR"(€)"; // { dg-bogus "invalid UTF-8 character <80>" "" { target c++23 } } +auto C1 = UR"(¿)"; // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D1 = UR"(À)"; // { dg-bogus "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E1 = UR"(Á)"; // { dg-bogus "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F1 = UR"(õ)"; // { dg-bogus "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G1 = UR"(ÿ)"; // { dg-bogus "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H1 = UR"(Â)"; // { dg-bogus "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I1 = UR"(à)"; // { dg-bogus "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J1 = UR"(à€¿)"; // { dg-bogus "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K1 = UR"(àŸ€)"; // { dg-bogus "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L1 = UR"(à¿)"; // { dg-bogus "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M1 = UR"(ì€)"; // { dg-bogus "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N1 = UR"(í €)"; // { dg-bogus "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O1 = UR"(ð€€€)"; // { dg-bogus "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P1 = UR"(ð¿¿)"; // { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q1 = UR"(ô€€)"; // { dg-bogus "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R1 = UR"(ý¿¿¿¿¿)"; // { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } +auto A2 = u8"Â€ß¿à €íŸ¿î€€ð€€ô¿¿"; // { dg-bogus "invalid UTF-8 character" } +auto B2 = u8"€"; // { dg-bogus "invalid UTF-8 character <80>" "" { target c++23 } } +auto C2 = u8"¿"; // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } } +auto D2 = u8"À"; // { dg-bogus "invalid UTF-8 character <c0>" "" { target c++23 } } +auto E2 = u8"Á"; // { dg-bogus "invalid UTF-8 character <c1>" "" { target c++23 } } +auto F2 = u8"õ"; // { dg-bogus "invalid UTF-8 character <f5>" "" { target c++23 } } +auto G2 = u8"ÿ"; // { dg-bogus "invalid UTF-8 character <ff>" "" { target c++23 } } +auto H2 = u8"Â"; // { dg-bogus "invalid UTF-8 character <c2>" "" { target c++23 } } +auto I2 = u8"à"; // { dg-bogus "invalid UTF-8 character <e0>" "" { target c++23 } } +auto J2 = u8"à€¿"; // { dg-bogus "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +auto K2 = u8"àŸ€"; // { dg-bogus "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +auto L2 = u8"à¿"; // { dg-bogus "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +auto M2 = u8"ì€"; // { dg-bogus "invalid UTF-8 character <ec><80>" "" { target c++23 } } +auto N2 = u8"í €"; // { dg-bogus "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +auto O2 = u8"ð€€€"; // { dg-bogus "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +auto P2 = u8"ð¿¿"; // { dg-bogus "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +auto Q2 = u8"ô€€"; // { dg-bogus "invalid UTF-8 character <f4><90><80><80>" "" { target c++23 } } +auto R2 = u8"ý¿¿¿¿¿"; // { dg-bogus "invalid UTF-8 character <fd><bf><bf><bf>" "" { target c++23 } } + // { dg-bogus "invalid UTF-8 character <bf>" "" { target c++23 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-9.C b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-9.C new file mode 100644 index 0000000..0afc945 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/Winvalid-utf8-9.C @@ -0,0 +1,25 @@ +// P2295R6 - Support for UTF-8 as a portable source file encoding +// This test intentionally contains various byte sequences which are not valid UTF-8 +// { dg-do preprocess } +// { dg-options "-finput-charset=UTF-8" } + +#define I(x) +I(Â€ß¿à €íŸ¿î€€ð€€ô¿¿) // { dg-bogus "invalid UTF-8 character" } + // { dg-error "is not valid in an identifier" "" { target *-*-* } .-1 } +I(€) // { dg-warning "invalid UTF-8 character <80>" "" { target c++23 } } +I(¿) // { dg-warning "invalid UTF-8 character <bf>" "" { target c++23 } } +I(À) // { dg-warning "invalid UTF-8 character <c0>" "" { target c++23 } } +I(Á) // { dg-warning "invalid UTF-8 character <c1>" "" { target c++23 } } +I(õ) // { dg-warning "invalid UTF-8 character <f5>" "" { target c++23 } } +I(ÿ) // { dg-warning "invalid UTF-8 character <ff>" "" { target c++23 } } +I(Â) // { dg-warning "invalid UTF-8 character <c2>" "" { target c++23 } } +I(à) // { dg-warning "invalid UTF-8 character <e0>" "" { target c++23 } } +I(à€¿) // { dg-warning "invalid UTF-8 character <e0><80><bf>" "" { target c++23 } } +I(àŸ€) // { dg-warning "invalid UTF-8 character <e0><9f><80>" "" { target c++23 } } +I(à¿) // { dg-warning "invalid UTF-8 character <e0><bf>" "" { target c++23 } } +I(ì€) // { dg-warning "invalid UTF-8 character <ec><80>" "" { target c++23 } } +I(í €) // { dg-warning "invalid UTF-8 character <ed><a0><80>" "" { target c++23 } } +I(ð€€€) // { dg-warning "invalid UTF-8 character <f0><80><80><80>" "" { target c++23 } } +I(ð¿¿) // { dg-warning "invalid UTF-8 character <f0><8f><bf><bf>" "" { target c++23 } } +I(ô€€) // { dg-error "is not valid in an identifier" } +I(ý¿¿¿¿¿) // { dg-error "is not valid in an identifier" } diff --git a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C index c1f91e7..d3e4072 100644 --- a/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C +++ b/gcc/testsuite/g++.dg/cpp23/feat-cxx2b.C @@ -557,3 +557,9 @@ #elif __cpp_multidimensional_subscript != 202110 # error "__cpp_multidimensional_subscript != 202110" #endif + +#ifndef __cpp_named_character_escapes +# error "__cpp_named_character_escapes" +#elif __cpp_named_character_escapes != 202207 +# error "__cpp_named_character_escapes != 202207" +#endif diff --git a/gcc/testsuite/g++.dg/cpp23/wchar-multi1.C b/gcc/testsuite/g++.dg/cpp23/wchar-multi1.C new file mode 100644 index 0000000..77fa3a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/wchar-multi1.C @@ -0,0 +1,42 @@ +// P2362R3 - Remove non-encodable wide character literals and multicharacter +// wide character literals. +// { dg-do compile } + +char a = 'a'; +int b = 'ab'; // { dg-warning "multi-character character constant" } +int c = '\u05D9'; // { dg-warning "multi-character character constant" } +#if __SIZEOF_INT__ > 2 +int d = '\U0001F525'; // { dg-warning "multi-character character constant" "" { target int32 } } +#endif +int e = 'abcd'; // { dg-warning "multi-character character constant" } +wchar_t f = L'f'; +wchar_t g = L'gh'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t h = L'ijkl'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t i = L'\U0001F525'; // { dg-error "character constant too long for its type" "" { target { c++23 && { ! 4byte_wchar_t } } } } + // { dg-warning "character constant too long for its type" "" { target { c++20_down && { ! 4byte_wchar_t } } } .-1 } +#ifdef __cpp_char8_t +typedef char8_t u8; +#else +typedef char u8; +#endif +#if __cpp_unicode_characters >= 201411 +u8 j = u8'j'; +u8 k = u8'kl'; // { dg-error "character constant too long for its type" "" { target c++17 } } +u8 l = u8'\U0001F525'; // { dg-error "character constant too long for its type" "" { target c++17 } } +#endif +#if __cpp_unicode_characters >= 200704 +char16_t m = u'm'; +char16_t n = u'no'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char16_t o = u'\u05D9'; +char16_t p = u'\U0001F525'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char32_t q = U'm'; +char32_t r = U'no'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char32_t s = U'\u05D9'; +char32_t t = U'\U0001F525'; +#endif +wchar_t u = L'\u0065\u0301'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t v = L'eÌ'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp23/wchar-multi2.C b/gcc/testsuite/g++.dg/cpp23/wchar-multi2.C new file mode 100644 index 0000000..a63e0ff --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/wchar-multi2.C @@ -0,0 +1,43 @@ +// P2362R3 - Remove non-encodable wide character literals and multicharacter +// wide character literals. +// { dg-do compile } +// { dg-options "-fshort-wchar" } + +char a = 'a'; +int b = 'ab'; // { dg-warning "multi-character character constant" } +int c = '\u05D9'; // { dg-warning "multi-character character constant" } +#if __SIZEOF_INT__ > 2 +int d = '\U0001F525'; // { dg-warning "multi-character character constant" "" { target int32 } } +#endif +int e = 'abcd'; // { dg-warning "multi-character character constant" } +wchar_t f = L'f'; +wchar_t g = L'gh'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t h = L'ijkl'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t i = L'\U0001F525'; // { dg-error "character constant too long for its type" "" { target { c++23 } } } + // { dg-warning "character constant too long for its type" "" { target { c++20_down } } .-1 } +#ifdef __cpp_char8_t +typedef char8_t u8; +#else +typedef char u8; +#endif +#if __cpp_unicode_characters >= 201411 +u8 j = u8'j'; +u8 k = u8'kl'; // { dg-error "character constant too long for its type" "" { target c++17 } } +u8 l = u8'\U0001F525'; // { dg-error "character constant too long for its type" "" { target c++17 } } +#endif +#if __cpp_unicode_characters >= 200704 +char16_t m = u'm'; +char16_t n = u'no'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char16_t o = u'\u05D9'; +char16_t p = u'\U0001F525'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char32_t q = U'm'; +char32_t r = U'no'; // { dg-error "character constant too long for its type" "" { target c++11 } } +char32_t s = U'\u05D9'; +char32_t t = U'\U0001F525'; +#endif +wchar_t u = L'\u0065\u0301'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } +wchar_t v = L'eÌ'; // { dg-error "character constant too long for its type" "" { target c++23 } } + // { dg-warning "character constant too long for its type" "" { target c++20_down } .-1 } diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C new file mode 100644 index 0000000..43b354f --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/utf-1.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++20 } } +// { dg-options { -gdwarf -dA } } + +// Test that all three use DW_ATE_UTF. +// { dg-final { scan-assembler-times {DW_AT_encoding \(0x10\)} 3 } } + +char8_t c8; +char16_t c16; +char32_t c32; diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C b/gcc/testsuite/g++.dg/ext/has-builtin-1.C new file mode 100644 index 0000000..fe25cb2 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C @@ -0,0 +1,133 @@ +// PR c++/106759 +// { dg-do compile } +// Verify that __has_builtin gives the correct answer for C++ built-ins. + +#if !__has_builtin (__builtin_addressof) +# error "__has_builtin (__builtin_addressof) failed" +#endif +#if !__has_builtin (__builtin_bit_cast) +# error "__has_builtin (__builtin_bit_cast) failed" +#endif +#if !__has_builtin (__builtin_launder) +# error "__has_builtin (__builtin_launder) failed" +#endif +#if !__has_builtin (__has_nothrow_assign) +# error "__has_builtin (__has_nothrow_assign) failed" +#endif +#if !__has_builtin (__has_nothrow_constructor) +# error "__has_builtin (__has_nothrow_constructor) failed" +#endif +#if !__has_builtin (__has_nothrow_copy) +# error "__has_builtin (__has_nothrow_copy) failed" +#endif +#if !__has_builtin (__has_trivial_assign) +# error "__has_builtin (__has_trivial_assign) failed" +#endif +#if !__has_builtin (__has_trivial_constructor) +# error "__has_builtin (__has_trivial_constructor) failed" +#endif +#if !__has_builtin (__has_trivial_copy) +# error "__has_builtin (__has_trivial_copy) failed" +#endif +#if !__has_builtin (__has_trivial_destructor) +# error "__has_builtin (__has_trivial_destructor) failed" +#endif +#if !__has_builtin (__has_unique_object_representations) +# error "__has_builtin (__has_unique_object_representations) failed" +#endif +#if !__has_builtin (__has_virtual_destructor) +# error "__has_builtin (__has_virtual_destructor) failed" +#endif +#if !__has_builtin (__is_abstract) +# error "__has_builtin (__is_abstract) failed" +#endif +#if !__has_builtin (__is_aggregate) +# error "__has_builtin (__is_aggregate) failed" +#endif +#if !__has_builtin (__is_base_of) +# error "__has_builtin (__is_base_of) failed" +#endif +#if !__has_builtin (__is_class) +# error "__has_builtin (__is_class) failed" +#endif +#if !__has_builtin (__is_empty) +# error "__has_builtin (__is_empty) failed" +#endif +#if !__has_builtin (__is_enum) +# error "__has_builtin (__is_enum) failed" +#endif +#if !__has_builtin (__is_final) +# error "__has_builtin (__is_final) failed" +#endif +#if !__has_builtin (__is_layout_compatible) +# error "__has_builtin (__is_layout_compatible) failed" +#endif +#if !__has_builtin (__is_literal_type) +# error "__has_builtin (__is_literal_type) failed" +#endif +#if !__has_builtin (__is_pointer_interconvertible_base_of) +# error "__has_builtin (__is_pointer_interconvertible_base_of) failed" +#endif +#if !__has_builtin (__is_pod) +# error "__has_builtin (__is_pod) failed" +#endif +#if !__has_builtin (__is_polymorphic) +# error "__has_builtin (__is_polymorphic) failed" +#endif +#if !__has_builtin (__is_same) +# error "__has_builtin (__is_same) failed" +#endif +#if !__has_builtin (__is_same_as) +# error "__has_builtin (__is_same_as) failed" +#endif +#if !__has_builtin (__is_standard_layout) +# error "__has_builtin (__is_standard_layout) failed" +#endif +#if !__has_builtin (__is_trivial) +# error "__has_builtin (__is_trivial) failed" +#endif +#if !__has_builtin (__is_trivially_assignable) +# error "__has_builtin (__is_trivially_assignable) failed" +#endif +#if !__has_builtin (__is_trivially_constructible) +# error "__has_builtin (__is_trivially_constructible) failed" +#endif +#if !__has_builtin (__is_trivially_copyable) +# error "__has_builtin (__is_trivially_copyable) failed" +#endif +#if !__has_builtin (__is_union) +# error "__has_builtin (__is_union) failed" +#endif +#if !__has_builtin (__underlying_type) +# error "__has_builtin (__underlying_type) failed" +#endif +#if !__has_builtin (__is_assignable) +# error "__has_builtin (__is_assignable) failed" +#endif +#if !__has_builtin (__is_constructible) +# error "__has_builtin (__is_constructible) failed" +#endif +#if !__has_builtin (__is_nothrow_assignable) +# error "__has_builtin (__is_nothrow_assignable) failed" +#endif +#if !__has_builtin (__is_nothrow_constructible) +# error "__has_builtin (__is_nothrow_constructible) failed" +#endif +#if !__has_builtin (__reference_constructs_from_temporary) +# error "__has_builtin (__reference_constructs_from_temporary) failed" +#endif +#if !__has_builtin (__reference_converts_from_temporary) +# error "__has_builtin (__reference_converts_from_temporary) failed" +#endif +#if !__has_builtin (__builtin_is_constant_evaluated) +# error "__has_builtin (__builtin_is_constant_evaluated) failed" +#endif +#if !__has_builtin (__builtin_source_location) +# error "__has_builtin (__builtin_source_location) failed" +#endif +#if !__has_builtin (__builtin_is_corresponding_member) +# error "__has_builtin (__builtin_is_corresponding_member) failed" +#endif +#if !__has_builtin (__builtin_is_pointer_interconvertible_with_class) +# error "__has_builtin (__builtin_is_pointer_interconvertible_with_class) failed" +#endif diff --git a/gcc/testsuite/g++.dg/init/elide8.C b/gcc/testsuite/g++.dg/init/elide8.C new file mode 100644 index 0000000..31f899b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/elide8.C @@ -0,0 +1,11 @@ +// CWG 2403 case 3: we can't elide this copy because the delegating constructor +// might be used to initialize a base. +// { dg-do compile { target c++11 } } + +struct Noncopyable { + Noncopyable() = default; + Noncopyable(const Noncopyable &) = delete; + Noncopyable(int) : Noncopyable(make()) {} // { dg-error "deleted" } + + static Noncopyable make(); +}; diff --git a/gcc/testsuite/g++.dg/other/PR23205.C b/gcc/testsuite/g++.dg/other/PR23205.C deleted file mode 100644 index 65ba1f6..0000000 --- a/gcc/testsuite/g++.dg/other/PR23205.C +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile { target stabs } } */ -/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types" } */ - -const int foobar = 4; -int foo () -{ - return foobar + 1; -} - -int main() -{ - int i; - i = foo(); - return i; -} - -/* { dg-final { scan-assembler ".stabs.*foobar:(c=i|S)" } } */ diff --git a/gcc/testsuite/g++.dg/other/pr23205-2.C b/gcc/testsuite/g++.dg/other/pr23205-2.C deleted file mode 100644 index 7b25c07..0000000 --- a/gcc/testsuite/g++.dg/other/pr23205-2.C +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile { target stabs } } */ -/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types -ftoplevel-reorder" } */ - -const int foobar = 4; -int foo () -{ - return foobar + 1; -} - -int main() -{ - int i; - i = foo(); - return i; -} - -/* { dg-final { scan-assembler ".stabs.*foobar:c=i" } } */ diff --git a/gcc/testsuite/g++.dg/parse/expr3.C b/gcc/testsuite/g++.dg/parse/expr3.C index 95d332f..1e16673 100644 --- a/gcc/testsuite/g++.dg/parse/expr3.C +++ b/gcc/testsuite/g++.dg/parse/expr3.C @@ -23,7 +23,7 @@ test (||, &&, 1, 1, 0, 0) test (&&, |, 5, 1, 1, 19) -test (|, ^, 1, 2, 2, 1) +test (|, ^, 1, 2, 0x2, 1) test (^, &, 1, 3, 2, 6) test (&, ==, 1, 3, 2, 0) test (==, <, 2, 0, 0, 0) diff --git a/gcc/testsuite/g++.dg/torture/pr90994.C b/gcc/testsuite/g++.dg/torture/pr90994.C new file mode 100644 index 0000000..8feb36f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr90994.C @@ -0,0 +1,40 @@ +// { dg-do compile } +// { dg-additional-options "-fnon-call-exceptions -Wuninitialized" } + +extern void printval(unsigned char v); + +inline int readbyte(unsigned char *__restrict presult, + unsigned char volatile *ptr) +{ + unsigned char v; + try { + v = *ptr; + } catch (...) { + return -1; + } + *presult = v; + return 0; +} + +int incorrectWarning(unsigned char volatile *ptr) +{ + int error; + unsigned char first; + unsigned char second; + + error = readbyte(&first, ptr); + asm("\n\n\n\n\n" : : "X" (error != 0)); + if (error != 0) + goto err; + + error = readbyte(&second, ptr); + if (error != 0) + goto err; + + printval(first); // { dg-bogus "uninitialized" } + printval(second); + return 0; + +err: + return error; +} diff --git a/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C index 6b1e879..dca7868 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C +++ b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-cddce2 -ffinite-loops" } */ +/* { dg-options "-O2 -fdump-tree-cddce2 -ffinite-loops -Wno-unused-result" } */ #include <string> #include <vector> diff --git a/gcc/testsuite/g++.dg/uninit-pred-5.C b/gcc/testsuite/g++.dg/uninit-pred-5.C new file mode 100644 index 0000000..8dfd987 --- /dev/null +++ b/gcc/testsuite/g++.dg/uninit-pred-5.C @@ -0,0 +1,94 @@ +// { dg-do compile } +// { dg-options "-O2 -Wuninitialized" } + +typedef int size_t; +typedef struct { +} max_align_t; +typedef struct tree_node *tree; +struct ht_identifier { + char str; + int len; +}; +struct cpp_hashnode { + ht_identifier ident; +}; +tree get_identifier_with_length(char *, size_t); +struct cpp_reader *parse_in; +typedef int edit_distance_t; +edit_distance_t get_edit_distance(char *); +template < typename > struct edit_distance_traits; +edit_distance_t get_edit_distance_cutoff(size_t); +template < typename GOAL_TYPE, typename CANDIDATE_TYPE > class best_match { +public: + typedef CANDIDATE_TYPE candidate_t; + typedef edit_distance_traits< candidate_t > candidate_traits; + best_match(GOAL_TYPE) + : m_goal(), m_goal_len(), m_best_candidate(), m_best_distance() {} + void consider(candidate_t candidate) { + size_t candidate_len = candidate_traits::get_length(candidate); + char candidate_str; + edit_distance_t dist = get_edit_distance(&candidate_str); + bool is_better = false; + if (dist) + is_better = true; + if (is_better) { + m_best_candidate = candidate; + m_best_candidate_len = candidate_len; + } + } + void set_best_so_far(CANDIDATE_TYPE) {} + candidate_t get_best_meaningful_candidate() { + edit_distance_t __trans_tmp_1; + if (m_best_candidate) { + size_t candidate_len = m_best_candidate_len; + __trans_tmp_1 = get_edit_distance_cutoff(candidate_len); // { dg-warning "may be used uninitialized" } + } + edit_distance_t cutoff = __trans_tmp_1; + if (cutoff) + ; + return m_best_candidate; + } + char m_goal; + size_t m_goal_len; + candidate_t m_best_candidate; + edit_distance_t m_best_distance; + size_t m_best_candidate_len; +}; +template <> struct edit_distance_traits< tree > { + static size_t get_length(tree); +}; +class name_hint {}; +class best_macro_match : public best_match< tree, cpp_hashnode * > { +public: + best_macro_match(cpp_reader *); +}; +struct c_binding { + tree id; + c_binding *prev; +}; +struct c_scope { + c_scope *outer; + c_binding bindings; +} * current_scope; +tree lookup_name_fuzzy_name; +void lookup_name_fuzzy() { + bool consider_implementation_names = 0; + best_match< tree, tree > bm(lookup_name_fuzzy_name); + for (c_scope *scope = current_scope; current_scope; + scope = scope->outer) + for (c_binding *binding = &scope->bindings; binding; + binding = binding->prev) + if (!consider_implementation_names) + bm.consider(binding->id); + best_macro_match bmm(parse_in); + cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate(); + if (best_macro) { + char id = best_macro->ident.str; + tree macro_as_identifier = + get_identifier_with_length(&id, best_macro->ident.len); + bm.set_best_so_far(macro_as_identifier); + } + tree best = bm.get_best_meaningful_candidate(); + if (best) + name_hint(); +} diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-10.C b/gcc/testsuite/g++.dg/warn/Wparentheses-10.C index 557db09..a5d28ef 100644 --- a/gcc/testsuite/g++.dg/warn/Wparentheses-10.C +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-10.C @@ -16,7 +16,7 @@ bar (int a, int b, int c) foo (1 & (2 ^ c)); foo (1 & 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 & 2) ^ 3); - foo (1 & (2 ^ 3)); + foo (1 & (0x2 ^ 3)); foo (a ^ b & c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) & c); foo (a ^ (b & c)); @@ -34,7 +34,7 @@ bar (int a, int b, int c) foo (1 + (2 ^ c)); foo (1 + 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 + 2) ^ 3); - foo (1 + (2 ^ 3)); + foo (1 + (0x2 ^ 3)); foo (a ^ b + c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) + c); foo (a ^ (b + c)); @@ -52,7 +52,7 @@ bar (int a, int b, int c) foo (1 - (2 ^ c)); foo (1 - 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 - 2) ^ 3); - foo (1 - (2 ^ 3)); + foo (1 - (0x2 ^ 3)); foo (a ^ b - c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) - c); foo (a ^ (b - c)); @@ -70,7 +70,7 @@ bar (int a, int b, int c) foo (1 >= (2 ^ c)); foo (1 >= 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 >= 2) ^ 3); - foo (1 >= (2 ^ 3)); + foo (1 >= (0x2 ^ 3)); foo (a ^ b >= c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) >= c); foo (a ^ (b >= c)); @@ -88,7 +88,7 @@ bar (int a, int b, int c) foo (1 == (2 ^ c)); foo (1 == 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 == 2) ^ 3); - foo (1 == (2 ^ 3)); + foo (1 == (0x2 ^ 3)); foo (a ^ b == c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) == c); foo (a ^ (b == c)); @@ -104,9 +104,9 @@ bar (int a, int b, int c) foo (1 < 2 ^ c); // { dg-warning "parentheses" "correct warning" } foo ((1 < 2) ^ c); foo (1 < (2 ^ c)); - foo (1 < 2 ^ 3); // { dg-warning "parentheses" "correct warning" } + foo (1 < 0x2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 < 2) ^ 3); - foo (1 < (2 ^ 3)); + foo (1 < (0x2 ^ 3)); foo (a ^ b < c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) < c); foo (a ^ (b < c)); diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-18.C b/gcc/testsuite/g++.dg/warn/Wparentheses-18.C index 83efaff..d50fad8 100644 --- a/gcc/testsuite/g++.dg/warn/Wparentheses-18.C +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-18.C @@ -42,9 +42,9 @@ bar (T a, T b, T c) foo (1 | 2 ^ c); // { dg-warning "parentheses" "correct warning" } foo ((1 | 2) ^ c); foo (1 | (2 ^ c)); - foo (1 | 2 ^ 3); // { dg-warning "parentheses" "correct warning" } + foo (1 | 0x2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 | 2) ^ 3); - foo (1 | (2 ^ 3)); + foo (1 | (0x2 ^ 3)); foo (a + b | c); // { dg-warning "parentheses" "correct warning" } foo ((a + b) | c); foo (a + (b | c)); diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-19.C b/gcc/testsuite/g++.dg/warn/Wparentheses-19.C index f0e2b80..2ad8036 100644 --- a/gcc/testsuite/g++.dg/warn/Wparentheses-19.C +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-19.C @@ -17,7 +17,7 @@ bar (T a, T b, T c) foo (1 & (2 ^ c)); foo (1 & 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 & 2) ^ 3); - foo (1 & (2 ^ 3)); + foo (1 & (0x2 ^ 3)); foo (a ^ b & c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) & c); foo (a ^ (b & c)); @@ -35,7 +35,7 @@ bar (T a, T b, T c) foo (1 + (2 ^ c)); foo (1 + 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 + 2) ^ 3); - foo (1 + (2 ^ 3)); + foo (1 + (0x2 ^ 3)); foo (a ^ b + c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) + c); foo (a ^ (b + c)); @@ -53,7 +53,7 @@ bar (T a, T b, T c) foo (1 - (2 ^ c)); foo (1 - 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 - 2) ^ 3); - foo (1 - (2 ^ 3)); + foo (1 - (0x2 ^ 3)); foo (a ^ b - c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) - c); foo (a ^ (b - c)); @@ -71,7 +71,7 @@ bar (T a, T b, T c) foo (1 >= (2 ^ c)); foo (1 >= 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 >= 2) ^ 3); - foo (1 >= (2 ^ 3)); + foo (1 >= (0x2 ^ 3)); foo (a ^ b >= c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) >= c); foo (a ^ (b >= c)); @@ -89,7 +89,7 @@ bar (T a, T b, T c) foo (1 == (2 ^ c)); foo (1 == 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 == 2) ^ 3); - foo (1 == (2 ^ 3)); + foo (1 == (0x2 ^ 3)); foo (a ^ b == c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) == c); foo (a ^ (b == c)); @@ -107,7 +107,7 @@ bar (T a, T b, T c) foo (1 < (2 ^ c)); foo (1 < 2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 < 2) ^ 3); - foo (1 < (2 ^ 3)); + foo (1 < (0x2 ^ 3)); foo (a ^ b < c); // { dg-warning "parentheses" "correct warning" } foo ((a ^ b) < c); foo (a ^ (b < c)); diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-9.C b/gcc/testsuite/g++.dg/warn/Wparentheses-9.C index 7c8f01d..69976b3b 100644 --- a/gcc/testsuite/g++.dg/warn/Wparentheses-9.C +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-9.C @@ -41,9 +41,9 @@ bar (int a, int b, int c) foo (1 | 2 ^ c); // { dg-warning "parentheses" "correct warning" } foo ((1 | 2) ^ c); foo (1 | (2 ^ c)); - foo (1 | 2 ^ 3); // { dg-warning "parentheses" "correct warning" } + foo (1 | 0x2 ^ 3); // { dg-warning "parentheses" "correct warning" } foo ((1 | 2) ^ 3); - foo (1 | (2 ^ 3)); + foo (1 | (0x2 ^ 3)); foo (a + b | c); // { dg-warning "parentheses" "correct warning" } foo ((a + b) | c); foo (a + (b | c)); diff --git a/gcc/testsuite/g++.dg/warn/Wself-move1.C b/gcc/testsuite/g++.dg/warn/Wself-move1.C new file mode 100644 index 0000000..5c9fc92 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wself-move1.C @@ -0,0 +1,125 @@ +// PR c++/81159 +// { dg-do compile { target c++11 } } +// { dg-options "-Wself-move" } + +// Define std::move. +namespace std { + template<typename _Tp> + struct remove_reference + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template<typename _Tp> + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } +} + +int g; + +struct S { + int x; + S(S&& o) { + x = std::move (x); // { dg-warning "moving '\[^\n\r]*S::x' of type .int. to itself" } + x = std::move (o.x); + o.x = std::move (x); + o.x = std::move (o.x); // { dg-warning "moving 'o.S::x' of type .int. to itself" } + } + void foo (int x) { + x = std::move (x); // { dg-warning "moving 'x' of type .int. to itself" } + } +}; + +struct X { + int x; + X(int x) : x(std::move (x)) { } +}; + +struct A {}; +struct B { A a; }; +struct C { C(); ~C(); }; +struct D { D(); D(const D&); D(D&&); D& operator=(const D&); }; + +void +test () +{ + int i = 42; + i = std::move (i); // { dg-warning "moving 'i' of type .int. to itself" } + (i) = std::move (i); // { dg-warning "moving 'i' of type .int. to itself" } + + g = std::move (g); // { dg-warning "moving 'g' of type .int. to itself" } + (g) = std::move (g); // { dg-warning "moving 'g' of type .int. to itself" } + + A a; + a = std::move (a); // { dg-warning "moving 'a' of type .A. to itself" } + (a) = std::move (a); // { dg-warning "moving 'a' of type .A. to itself" } + + B b; + b = std::move (b); // { dg-warning "moving 'b' of type .B. to itself" } + (b) = std::move (b); // { dg-warning "moving 'b' of type .B. to itself" } + b.a = std::move (b.a); // { dg-warning "moving 'b.B::a' of type .A. to itself" } + (b.a) = std::move (b.a); // { dg-warning "moving 'b.B::a' of type .A. to itself" } + + C c; + c = std::move (c); // { dg-warning "moving 'c' of type .C. to itself" } + D d; + d = std::move (d); // { dg-warning "moving 'd' of type .D. to itself" } +} + +template<typename T> +void ttest () +{ + T t; + t = std::move (t); // { dg-warning "moving 't' of type .A. to itself" } +} + +template void ttest<A>(); + +void +testref (int &r, int &&rr) +{ + r = std::move (r); // { dg-warning "moving 'r' of type .int. to itself" } + rr = std::move (rr); // { dg-warning "moving 'rr' of type .int. to itself" } +} + +// Test various other arguments to std::move. +template<typename T> +void +testargs (T *Tptr, T **Tpptr, T& Tref, T&& Trref, const T *Tcptr) +{ + Tptr = std::move (Tptr); // { dg-warning "moving 'Tptr' of type 'int\\*' to itself" } + *Tptr = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" } + *Tptr = std::move (*(Tptr)); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" } + *(Tptr) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" } + *(Tptr + 1) = std::move (*(Tptr + 1)); // { dg-warning "moving '\[^\n\r]*Tptr\[^\n\r]*' of type 'int' to itself" } + *(Tptr + 1) = std::move (*(Tptr + 2)); + (*(Tptr)) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" } + *Tpptr = std::move (*Tpptr); // { dg-warning "moving '\\* Tpptr' of type 'int\\*' to itself" } + **Tpptr = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" } + Tref = std::move (Tref); // { dg-warning "moving 'Tref' of type 'int' to itself" } + Trref = std::move (Trref); // { dg-warning "moving 'Trref' of type 'int' to itself" } + Tcptr = std::move (Tcptr); // { dg-warning "moving 'Tcptr' of type 'const int\\*' to itself" } + (Tptr) = std::move (Tptr); // { dg-warning "moving 'Tptr' of type 'int\\*' to itself" } + (*Tptr) = std::move (*Tptr); // { dg-warning "moving '\\* Tptr' of type 'int' to itself" } + (*Tpptr) = std::move (*Tpptr); // { dg-warning "moving '\\* Tpptr' of type 'int\\*' to itself" } + (**Tpptr) = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" } + (*(*(Tpptr))) = std::move (**Tpptr); // { dg-warning "moving '\\* \\* Tpptr' of type 'int' to itself" } + (Tref) = std::move (Tref); // { dg-warning "moving 'Tref' of type 'int' to itself" } + (Trref) = std::move (Trref); // { dg-warning "moving 'Trref' of type 'int' to itself" } + (Tcptr) = std::move (Tcptr); // { dg-warning "moving 'Tcptr' of type 'const int\\*' to itself" } +} + +void +call_testargs () +{ + int i = 42; + int *p = &i; + testargs<int>(&i, &p, i, 42, &i); +} diff --git a/gcc/testsuite/g++.dg/warn/Wxor-used-as-pow-named-op.C b/gcc/testsuite/g++.dg/warn/Wxor-used-as-pow-named-op.C new file mode 100644 index 0000000..4899d72 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wxor-used-as-pow-named-op.C @@ -0,0 +1,8 @@ +/* Verify that -Wxor-used-as-pow only warns with ^ and not with + named "xor". */ + +int t2_16 = 2^16; /* { dg-warning "result of '2\\^16' is 18; did you mean '1 << 16' \\(65536\\)\\?" } */ +int t2x16 = 2 xor 16; + +int t10_6 = 10^6; /* { dg-warning "result of '10\\^6' is 12; did you mean '1e6'\\?" } */ +int t10x6 = 10 xor 6; diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr96974.C b/gcc/testsuite/g++.target/aarch64/sve/pr96974.C index 54000f5..2f6ebd6 100644 --- a/gcc/testsuite/g++.target/aarch64/sve/pr96974.C +++ b/gcc/testsuite/g++.target/aarch64/sve/pr96974.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -march=armv8.2-a+sve -fdisable-tree-fre4 -fdump-tree-slp-details" } */ +/* { dg-options "-Ofast -march=armv8.2-a+sve -fdisable-tree-fre4" } */ float a; int @@ -14,5 +14,3 @@ struct c { } int coeffs[10]; } f; - -/* { dg-final { scan-tree-dump "Not vectorized: Incompatible number of vector subparts between" "slp1" { target lp64 } } } */ diff --git a/gcc/testsuite/g++.target/i386/pr106627.C b/gcc/testsuite/g++.target/i386/pr106627.C new file mode 100644 index 0000000..e993d82 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr106627.C @@ -0,0 +1,28 @@ +/* PR c++/103012 Exception handling with multiversioned functions */ +/* { dg-do run } */ +/* { dg-require-ifunc "" } */ + +extern "C" void abort (void); + +__attribute__((target("default"))) +void f() { + throw 1; +} + +__attribute__((target("sse4.2,bmi"))) +void f() { + throw 2; +} + +int main() +{ + try { + f(); + } + catch(...) + { + return 0; + } + + abort (); +} diff --git a/gcc/testsuite/g++.target/powerpc/pr101322.C b/gcc/testsuite/g++.target/powerpc/pr101322.C new file mode 100644 index 0000000..43eaf3a --- /dev/null +++ b/gcc/testsuite/g++.target/powerpc/pr101322.C @@ -0,0 +1,17 @@ +/* PR target/101322 */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10" } */ + +/* Verify we don't ICE on the following test cases. */ + +void +foo (char *resp, char *vpp) +{ + __builtin_vsx_disassemble_pair (resp, (__vector_pair *) vpp); +} + +void +bar (char *resp, char *vpp) +{ + __builtin_mma_disassemble_acc (resp, (__vector_quad *)vpp); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106101.c b/gcc/testsuite/gcc.c-torture/compile/pr106101.c new file mode 100644 index 0000000..dec6608 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr106101.c @@ -0,0 +1,62 @@ +/* { dg-do compile } */ + +extern char *globerr; +char **ftpglob(); + +static const int yypgoto[] = +{ + -82, -82, -82, -82 +}; + +static const int yydefgoto[] = +{ + 0, 1, 36, 37 +}; + +static const int yytable[] = +{ + 43, 129, 88, 89 +}; + +static const int yycheck[] = +{ + 8, 82, 4, 5 +}; + + +int yyparse (void) +{ + int yystate = 0; + int *yyvsp = 0; + + int yyn; + int yyresult; + int yyval; + +yyreduce: + + switch (yyn) + { + case 72: { + + if (strncmp( yyvsp[0], "~", 1) == 0) { + *(char **)&(yyval) = *ftpglob(yyvsp[0]); + if (globerr != 0) { + yyval = 0; + } + free(yyvsp[0]); + } + } + break; + } + + *++yyvsp = yyval; + + { + const int yyi = yypgoto[0] + *yyvsp; + yystate = (yycheck[yyi] == *yyvsp ? 0 : 0); + } + + return yyresult; +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/hugeval.x b/gcc/testsuite/gcc.c-torture/execute/ieee/hugeval.x index c66de1c..a6dad81 100644 --- a/gcc/testsuite/gcc.c-torture/execute/ieee/hugeval.x +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/hugeval.x @@ -2,9 +2,6 @@ # instead of +Infinity. global target_triplet -if { [istarget "hppa*-*-hpux9*"] || [istarget "hppa*-*-hpux10*"] } { - set torture_execute_xfail "$target_triplet" -} # VxWorks kernel mode has the same problem. if {[istarget "*-*-vxworks*"]} { diff --git a/gcc/testsuite/gcc.dg/20040813-1.c b/gcc/testsuite/gcc.dg/20040813-1.c deleted file mode 100644 index 9cf664d..0000000 --- a/gcc/testsuite/gcc.dg/20040813-1.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Test lang in N_SO stab. */ -/* Contributed by Devang Patel <dpatel@apple.com> */ - -/* { dg-do compile { target stabs } } */ -/* { dg-options "-gstabs" } */ - -int -main () -{ - return 0; -} - -/* { dg-final { scan-assembler ".stabs.*100,0,2" } } */ - diff --git a/gcc/testsuite/gcc.dg/Wparentheses-6.c b/gcc/testsuite/gcc.dg/Wparentheses-6.c index 2d2cc16..260b6ad 100644 --- a/gcc/testsuite/gcc.dg/Wparentheses-6.c +++ b/gcc/testsuite/gcc.dg/Wparentheses-6.c @@ -43,9 +43,9 @@ bar (int a, int b, int c) foo (1 | 2 ^ c); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 | 2) ^ c); foo (1 | (2 ^ c)); - foo (1 | 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ + foo (1 | 0x2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 | 2) ^ 3); - foo (1 | (2 ^ 3)); + foo (1 | (0x2 ^ 3)); foo (a + b | c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a + b) | c); foo (a + (b | c)); diff --git a/gcc/testsuite/gcc.dg/Wparentheses-7.c b/gcc/testsuite/gcc.dg/Wparentheses-7.c index f351696..6805094 100644 --- a/gcc/testsuite/gcc.dg/Wparentheses-7.c +++ b/gcc/testsuite/gcc.dg/Wparentheses-7.c @@ -18,7 +18,7 @@ bar (int a, int b, int c) foo (1 & (2 ^ c)); foo (1 & 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 & 2) ^ 3); - foo (1 & (2 ^ 3)); + foo (1 & (0x2 ^ 3)); foo (a ^ b & c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) & c); foo (a ^ (b & c)); @@ -36,7 +36,7 @@ bar (int a, int b, int c) foo (1 + (2 ^ c)); foo (1 + 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 + 2) ^ 3); - foo (1 + (2 ^ 3)); + foo (1 + (0x2 ^ 3)); foo (a ^ b + c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) + c); foo (a ^ (b + c)); @@ -54,7 +54,7 @@ bar (int a, int b, int c) foo (1 - (2 ^ c)); foo (1 - 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 - 2) ^ 3); - foo (1 - (2 ^ 3)); + foo (1 - (0x2 ^ 3)); foo (a ^ b - c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) - c); foo (a ^ (b - c)); @@ -72,7 +72,7 @@ bar (int a, int b, int c) foo (1 >= (2 ^ c)); foo (1 >= 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 >= 2) ^ 3); - foo (1 >= (2 ^ 3)); + foo (1 >= (0x2 ^ 3)); foo (a ^ b >= c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) >= c); foo (a ^ (b >= c)); @@ -90,7 +90,7 @@ bar (int a, int b, int c) foo (1 == (2 ^ c)); foo (1 == 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 == 2) ^ 3); - foo (1 == (2 ^ 3)); + foo (1 == (0x2 ^ 3)); foo (a ^ b == c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) == c); foo (a ^ (b == c)); @@ -108,7 +108,7 @@ bar (int a, int b, int c) foo (1 < (2 ^ c)); foo (1 < 2 ^ 3); /* { dg-warning "parentheses" "correct warning" } */ foo ((1 < 2) ^ 3); - foo (1 < (2 ^ 3)); + foo (1 < (0x2 ^ 3)); foo (a ^ b < c); /* { dg-warning "parentheses" "correct warning" } */ foo ((a ^ b) < c); foo (a ^ (b < c)); diff --git a/gcc/testsuite/gcc.dg/autopar/pr106737.c b/gcc/testsuite/gcc.dg/autopar/pr106737.c new file mode 100644 index 0000000..1aa65f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/autopar/pr106737.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target fgraphite } } */ +/* { dg-options "-O -floop-parallelize-all -ftree-parallelize-loops=2 -fno-tree-dce" } */ + +void +foo (int x) +{ + int a[2]; + int b, c = 0; + + for (b = 0; b < 2; ++b) + a[b] = 0; + for (b = 0; b < 2; ++b) + a[b] = 0; + + while (c < 1) + while (x < 1) + ++x; +} diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-1.c b/gcc/testsuite/gcc.dg/c11-empty-init-1.c new file mode 100644 index 0000000..120c282 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-empty-init-1.c @@ -0,0 +1,25 @@ +/* Test C11 does not support empty initializers. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +struct s { int a; }; +struct s s = {}; /* { dg-error "empty initializer" } */ +int x = {}; /* { dg-error "empty initializer" } */ +float y = {}; /* { dg-error "empty initializer" } */ +void *p = {}; /* { dg-error "empty initializer" } */ +union u { int a; long b; }; +union u z = {}; /* { dg-error "empty initializer" } */ +int aa[2] = {}; /* { dg-error "empty initializer" } */ + +void +f (int a) +{ + int vla[a] = {}; /* { dg-error "empty initializer" } */ + struct s as = {}; /* { dg-error "empty initializer" } */ + int ax = {}; /* { dg-error "empty initializer" } */ + float ay = {}; /* { dg-error "empty initializer" } */ + void *ap = {}; /* { dg-error "empty initializer" } */ + union u az = {}; /* { dg-error "empty initializer" } */ + int aaa[2] = {}; /* { dg-error "empty initializer" } */ + int t = (int) {}; /* { dg-error "empty initializer" } */ +} diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-2.c b/gcc/testsuite/gcc.dg/c11-empty-init-2.c new file mode 100644 index 0000000..3ec7c51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-empty-init-2.c @@ -0,0 +1,25 @@ +/* Test C11 does not support empty initializers. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic" } */ + +struct s { int a; }; +struct s s = {}; /* { dg-warning "empty initializer" } */ +int x = {}; /* { dg-warning "empty initializer" } */ +float y = {}; /* { dg-warning "empty initializer" } */ +void *p = {}; /* { dg-warning "empty initializer" } */ +union u { int a; long b; }; +union u z = {}; /* { dg-warning "empty initializer" } */ +int aa[2] = {}; /* { dg-warning "empty initializer" } */ + +void +f (int a) +{ + int vla[a] = {}; /* { dg-warning "empty initializer" } */ + struct s as = {}; /* { dg-warning "empty initializer" } */ + int ax = {}; /* { dg-warning "empty initializer" } */ + float ay = {}; /* { dg-warning "empty initializer" } */ + void *ap = {}; /* { dg-warning "empty initializer" } */ + union u az = {}; /* { dg-warning "empty initializer" } */ + int aaa[2] = {}; /* { dg-warning "empty initializer" } */ + int t = (int) {}; /* { dg-warning "empty initializer" } */ +} diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-3.c b/gcc/testsuite/gcc.dg/c11-empty-init-3.c new file mode 100644 index 0000000..fd43fa7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-empty-init-3.c @@ -0,0 +1,25 @@ +/* Test C11 does not support empty initializers. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -Wc11-c2x-compat" } */ + +struct s { int a; }; +struct s s = {}; /* { dg-warning "empty initializer" } */ +int x = {}; /* { dg-warning "empty initializer" } */ +float y = {}; /* { dg-warning "empty initializer" } */ +void *p = {}; /* { dg-warning "empty initializer" } */ +union u { int a; long b; }; +union u z = {}; /* { dg-warning "empty initializer" } */ +int aa[2] = {}; /* { dg-warning "empty initializer" } */ + +void +f (int a) +{ + int vla[a] = {}; /* { dg-warning "empty initializer" } */ + struct s as = {}; /* { dg-warning "empty initializer" } */ + int ax = {}; /* { dg-warning "empty initializer" } */ + float ay = {}; /* { dg-warning "empty initializer" } */ + void *ap = {}; /* { dg-warning "empty initializer" } */ + union u az = {}; /* { dg-warning "empty initializer" } */ + int aaa[2] = {}; /* { dg-warning "empty initializer" } */ + int t = (int) {}; /* { dg-warning "empty initializer" } */ +} diff --git a/gcc/testsuite/gcc.dg/c11-nullptr-1.c b/gcc/testsuite/gcc.dg/c11-nullptr-1.c new file mode 100644 index 0000000..c4faedc --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-nullptr-1.c @@ -0,0 +1,10 @@ +/* Test that in pre-C23 modes, nullptr is a normal identifier, + not a keyword. */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int nullptr; + +void +f (int nullptr) +{ +} diff --git a/gcc/testsuite/gcc.dg/c11-unproto-3.c b/gcc/testsuite/gcc.dg/c11-unproto-3.c new file mode 100644 index 0000000..b0e4bf3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-unproto-3.c @@ -0,0 +1,19 @@ +/* Test function declarations without prototypes for C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +void f1 (); +void +f1a (void) +{ + f1 (1, 2); +} + +void f2 (); +void f2 (int); + +void f3 (); + +_Static_assert (_Generic (f3, + void (*) (int) : 1, + default : 3) == 1, "unprototyped test"); diff --git a/gcc/testsuite/gcc.dg/c17-nullptr-1.c b/gcc/testsuite/gcc.dg/c17-nullptr-1.c new file mode 100644 index 0000000..92e43b9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c17-nullptr-1.c @@ -0,0 +1,10 @@ +/* Test that in pre-C23 modes, nullptr is a normal identifier, + not a keyword. */ +/* { dg-options "-std=c17 -pedantic-errors" } */ + +int nullptr; + +void +f (int nullptr) +{ +} diff --git a/gcc/testsuite/gcc.dg/c17-nullptr-2.c b/gcc/testsuite/gcc.dg/c17-nullptr-2.c new file mode 100644 index 0000000..a6ad770 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c17-nullptr-2.c @@ -0,0 +1,10 @@ +/* Test that we don't predefine `nullptr' pre-C2X. */ +/* { dg-do compile } */ +/* { dg-options "-std=c17 -pedantic-errors" } */ + +int * +fn (int *p) +{ + p = nullptr; /* { dg-error "'nullptr' undeclared" } */ + return p; +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c index 44f2cc9..7c01317 100644 --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c @@ -3,7 +3,8 @@ /* { dg-options "-std=c2x -pedantic-errors" } */ /* This attribute is not valid in most cases on types other than their - definitions, or on statements, or as an attribute-declaration. */ + definitions, or on labels, or on statements, or as an + attribute-declaration. */ [[deprecated]]; /* { dg-error "ignored" } */ @@ -21,4 +22,10 @@ f (void) int a; [[deprecated]]; /* { dg-error "ignored" } */ [[deprecated]] a = 1; /* { dg-error "ignored" } */ + [[deprecated]] label: ; /* { dg-error "ignored" } */ + switch (var) + { + [[deprecated]] case 1: ; /* { dg-error "ignored" } */ + [[deprecated]] default: ; /* { dg-error "ignored" } */ + } } diff --git a/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-2.c b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-2.c index 9d69959..b65bcbe 100644 --- a/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-2.c +++ b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-2.c @@ -33,6 +33,10 @@ f (int a) case 5: b += 5; break; + [[fallthrough]] case 6: break; /* { dg-error "ignored" } */ + [[fallthrough]] default: break; /* { dg-error "ignored" } */ } [[fallthrough]] return b; /* { dg-error "ignored" } */ + [[fallthrough]] label: ; /* { dg-error "ignored" } */ + goto label; } diff --git a/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-1.c b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-1.c index 477f30d..7090a3f 100644 --- a/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-1.c +++ b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-1.c @@ -14,7 +14,9 @@ g ([[maybe_unused]] int x, int y) [[maybe_unused]] int a; int b [[__maybe_unused__]]; int c [[maybe_unused]]; + [[__maybe_unused__]] label1: c = y; + [[maybe_unused]] label2: return y; } @@ -29,3 +31,14 @@ union [[maybe_unused]] u { int x; }; enum [[maybe_unused]] eu { E2 }; union u2 { [[maybe_unused]] int a; int b [[maybe_unused]]; } y; + +void +g2 (int x) +{ + switch (x) + { + [[maybe_unused]] case 1: ; + [[__maybe_unused__]] case 2: ; + [[maybe_unused]] default: ; + } +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c index 45c4d50..0ed2ebe 100644 --- a/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c +++ b/gcc/testsuite/gcc.dg/c2x-attr-nodiscard-2.c @@ -39,4 +39,10 @@ f (void) [[nodiscard ("reason")]] int b = 1; /* { dg-error "can only be applied" } */ [[nodiscard]]; /* { dg-error "ignored" } */ [[nodiscard]] a = 1; /* { dg-error "ignored" } */ + [[nodiscard]] label: ; /* { dg-error "can only be applied" } */ + switch (var) + { + [[nodiscard]] case 1: ; /* { dg-error "can only be applied" } */ + [[nodiscard]] default: ; /* { dg-error "can only be applied" } */ + } } diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-1.c b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c new file mode 100644 index 0000000..1487a2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c @@ -0,0 +1,80 @@ +/* Test C2X support for empty initializers: valid use cases. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +extern void exit (int); +extern void abort (void); + +struct s { int a; }; +struct s s = {}; +int x = {}; +float y = {}; +void *p = {}; +union u { int a; long b; }; +union u z = {}; +int aa[2] = {}; + +void +f (int a) +{ + volatile int vla[a] = {}; + struct s as = {}; + int ax = {}; + float ay = {}; + void *ap = {}; + union u az = {}; + int aaa[2] = {}; + for (int i = 0; i < a; i++) + if (vla[i] != 0) + abort (); + if (as.a != 0) + abort (); + if (ax != 0) + abort (); + if (ay != 0) + abort (); + if (ap != 0) + abort (); + if (az.a != 0) + abort (); + if (aaa[0] != 0) + abort (); + if (aaa[1] != 0) + abort (); + if ((int) {} != 0) + abort (); + if ((float) {} != 0) + abort (); + if ((struct s) {}.a != 0) + abort (); + if ((union u) {}.a != 0) + abort (); + if ((int [5]) {}[2] != 0) + abort (); + /* Overwrite contents of vla before second call to make it more likely stack + contents are nonzero if proper initialization did not occur. */ + for (int i = 0; i < a; i++) + vla[i] = -1; +} + +int +main (void) +{ + f (100); + f (100); + if (s.a != 0) + abort (); + if (x != 0) + abort (); + if (y != 0) + abort (); + if (p != 0) + abort (); + if (z.a != 0) + abort (); + if (aa[0] != 0) + abort (); + if (aa[1] != 0) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-2.c b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c new file mode 100644 index 0000000..0dc81ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c @@ -0,0 +1,18 @@ +/* Test C2X support for empty initializers: invalid use cases. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +/* Empty initialization is invalid for arrays of unknown size. This is + diagnosed via the diagnostic for zero-size arrays. */ +int x[] = {}; /* { dg-error "zero or negative size array" } */ + +void +f (int a) +{ + int x1[] = {}; /* { dg-error "zero or negative size array" } */ + int x2[][a] = {}; /* { dg-error "zero or negative size array" } */ + /* Nonempty VLA initializers are still invalid. */ + int x3[a] = { 0 }; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */ + /* Variable-size compound literals are still invalid. */ + (void) (int [a]) {}; /* { dg-error "compound literal has variable size" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-3.c b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c new file mode 100644 index 0000000..472f816 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c @@ -0,0 +1,25 @@ +/* Test empty initializers diagnosed in C2X mode with -Wc11-c2x-compat. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -Wc11-c2x-compat" } */ + +struct s { int a; }; +struct s s = {}; /* { dg-warning "empty initializer" } */ +int x = {}; /* { dg-warning "empty initializer" } */ +float y = {}; /* { dg-warning "empty initializer" } */ +void *p = {}; /* { dg-warning "empty initializer" } */ +union u { int a; long b; }; +union u z = {}; /* { dg-warning "empty initializer" } */ +int aa[2] = {}; /* { dg-warning "empty initializer" } */ + +void +f (int a) +{ + int vla[a] = {}; /* { dg-warning "empty initializer" } */ + struct s as = {}; /* { dg-warning "empty initializer" } */ + int ax = {}; /* { dg-warning "empty initializer" } */ + float ay = {}; /* { dg-warning "empty initializer" } */ + void *ap = {}; /* { dg-warning "empty initializer" } */ + union u az = {}; /* { dg-warning "empty initializer" } */ + int aaa[2] = {}; /* { dg-warning "empty initializer" } */ + int t = (int) {}; /* { dg-warning "empty initializer" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c index d6c4c6d..6a379e9 100644 --- a/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c +++ b/gcc/testsuite/gcc.dg/c2x-has-c-attribute-2.c @@ -10,11 +10,11 @@ #error "bad result for __nodiscard__" #endif -#if __has_c_attribute(maybe_unused) != 201904L +#if __has_c_attribute(maybe_unused) != 202106L #error "bad result for maybe_unused" #endif -#if __has_c_attribute(__maybe_unused__) != 201904L +#if __has_c_attribute(__maybe_unused__) != 202106L #error "bad result for __maybe_unused__" #endif @@ -26,11 +26,11 @@ #error "bad result for __deprecated__" #endif -#if __has_c_attribute (fallthrough) != 201904L +#if __has_c_attribute (fallthrough) != 201910L #error "bad result for fallthrough" #endif -#if __has_c_attribute (__fallthrough__) != 201904L +#if __has_c_attribute (__fallthrough__) != 201910L #error "bad result for __fallthrough__" #endif diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-1.c b/gcc/testsuite/gcc.dg/c2x-nullptr-1.c new file mode 100644 index 0000000..9501b51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-1.c @@ -0,0 +1,298 @@ +/* Test valid usage of C23 nullptr. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors -Wall -Wextra -Wno-unused-variable" } */ + +#include <stdarg.h> + +typedef __typeof__(nullptr) nullptr_t; + +void f1 (nullptr_t) { } +void f2 (int *) { } +void f3 (_Bool) { } +nullptr_t cmp (void) { return nullptr; } + +/* The type nullptr_t shall not be converted to any type other than void, bool or + a pointer type. No type other than nullptr_t shall be converted to nullptr_t. */ +void +test1 (void) +{ + const nullptr_t nptr = nullptr; + static nullptr_t static_nptr; + int *p1 = nullptr; + void *p2 = nullptr; + float *p3 = nullptr; + void (*p4)(int) = nullptr; + int (*p5)[10] = nullptr; + int *p6 = nptr; + void *p7 = nptr; + float *p8 = nptr; + void (*p9)(int) = nptr; + int (*p10)[10] = nptr; + int *p11 = (int *) nullptr; + int *p12 = (int *) nptr; + int *p13 = (nullptr); + int *p14 = _Generic(0, int : nullptr); + if (nullptr || p1 || p2 || p3 || p4 || p5 || p6 || p7 || p8 || p9 || p10 + || p11 || p12 || p13 || p14) + __builtin_abort (); + + _Bool b1 = nullptr; + _Bool b2 = (_Bool) nullptr; + _Bool b3 = nptr; + _Bool b4 = (_Bool) nptr; + _Bool b5 = _Generic(0, int : nullptr); + if (b1 || b2 || b3 || b4 || b5 || (_Bool) nullptr || (_Bool) nptr) + __builtin_abort (); + + __auto_type a1 = nullptr; + __auto_type a2 = nptr; + + /* We can convert nullptr_t to nullptr_t. */ + __typeof__(nullptr) x = nullptr; + f1 (x); + f1 (nullptr); + f1 (_Generic(0, int : nullptr)); + f2 (x); + f2 (nullptr); + f3 (nullptr); + + const nullptr_t np1 = nullptr; + const nullptr_t np2 = np1; + (void) nullptr; + (void) np1; + (void) np2; + (void) cmp (); + (void)(nullptr_t) nullptr; +} + +/* Test valid comparison. */ +void +test2 (int *p) +{ + /* If both operands have type nullptr_t or one operand has type nullptr_t + and the other is a null pointer constant, they compare equal. */ + const nullptr_t nptr = nullptr; + int r = 0; + + /* Both operands have type nullptr_t. */ + r |= nullptr != nullptr; + r |= cmp () != nullptr; + r |= nullptr != cmp (); + r |= !(nullptr == nullptr); + r |= !(cmp () == nullptr); + r |= !(nullptr == cmp ()); + r |= nptr != nptr; + r |= cmp () != nptr; + r |= nptr != cmp (); + r |= !(nptr == nptr); + r |= !(cmp () == nptr); + r |= !(nptr == cmp ()); + + /* One operand has type nullptr_t and the other is a null pointer constant. */ + r |= nullptr != (void *) 0; + r |= _Generic(0, int : nullptr) != (void *) 0; + r |= (nullptr) != (void *) 0; + r |= !(nullptr == (void *) 0); + r |= (void *) 0 != nullptr; + r |= (void *) 0 != (nullptr); + r |= !((void *) 0 == nullptr); + r |= nullptr != 0; + r |= _Generic(0, int : nullptr) != 0; + r |= (nullptr) != 0; + r |= 0 != nullptr; + r |= 0 != (nullptr); + r |= !(nullptr == 0); + r |= !(0 == nullptr); + r |= nullptr != 0u; + r |= 0u != nullptr; + r |= !(nullptr == 0u); + r |= !(0u == nullptr); + r |= nptr != (void *) 0; + r |= !(nptr == (void *) 0); + r |= (void *) 0 != nptr; + r |= !((void *) 0 == nptr); + r |= nptr != 0; + r |= 0 != nptr; + r |= !(nptr == 0); + r |= !(0 == nptr); + r |= nptr != 0u; + r |= 0u != nptr; + r |= !(nptr == 0u); + r |= !(0u == nptr); + r |= nptr != _Generic(0, int : nullptr); + r |= _Generic(0, int : nullptr) != nptr; + if (r) + __builtin_abort (); + + /* One operand is a pointer and the other is a null pointer constant. */ + (void) (p == nullptr); + (void) (p != nullptr); + (void) (nullptr == p); + (void) (nullptr != p); + (void) (p == (nullptr)); + (void) (p != (nullptr)); + (void) ((nullptr) == p); + (void) ((nullptr) != p); + (void) ((void *)nullptr == nullptr); + (void) ((void *)nullptr != nullptr); + (void) (nullptr == (void *)nullptr); + (void) (nullptr != (void *)nullptr); + (void) (p == _Generic(0, int : nullptr)); + (void) (p != _Generic(0, int : nullptr)); + (void) (_Generic(0, int : nullptr) == p); + (void) (_Generic(0, int : nullptr) != p); +} + +/* Test ?:. */ +void +test3 (int *p, _Bool b) +{ + int x = nullptr ? 1 : 2; + (void) x; + const nullptr_t nptr = nullptr; + /* One of the following shall hold for the second and third operands: + -- both operands have nullptr_t type. */ + __auto_type r1 = b ? nullptr : nullptr; + __auto_type r2 = b ? nptr : nptr; + /* -- one operand is a pointer and the other is a null pointer constant + or has type nullptr_t; */ + __auto_type r3 = b ? p : nullptr; + __auto_type r4 = b ? nullptr : p; + __auto_type r5 = b ? nptr : p; + __auto_type r6 = b ? p : nptr; + __auto_type r7 = b ? 0 : p; + __auto_type r8 = b ? p : 0; + __auto_type r9 = b ? p : cmp (); + __auto_type r10 = b ? cmp () : p; + __auto_type r11 = b ? p : _Generic(0, int : nullptr); + __auto_type r12 = b ? _Generic(0, int : nullptr) : p; +} + +void test_arg1 (const nullptr_t, _Atomic nullptr_t, volatile nullptr_t) { } +void test_arg2 (_Atomic int *, const int *, volatile int *) { } +void test_arg3 (_Atomic _Bool, const _Bool, volatile _Bool) { } +nullptr_t retn (void) { return nullptr; } +_Atomic int *ai (void) { return nullptr; } +const int *ci (void) { return nullptr; } +volatile int *vi (void) { return nullptr; } +_Bool retb (void) { return nullptr; } + +/* Simple assignment. */ +void +test4 (void) +{ + /* -- the left operand has an atomic, qualified, or unqualified version of + the nullptr_t type and the type of the right is nullptr_t; */ + nullptr_t n1; + const nullptr_t n2 = nullptr; + _Atomic nullptr_t n3 = nullptr; + volatile nullptr_t n4 = nullptr; + _Atomic volatile nullptr_t n5 = nullptr; + n1 = nullptr; + n3 = nullptr; + n4 = nullptr; + n5 = nullptr; + n5 = _Generic(0, int : nullptr); + /* -- the left operand is an atomic, qualified, or unqualified pointer, + and the type of the right is nullptr_t; */ + int *p1 = cmp (); + _Atomic int *p2 = cmp (); + const int *volatile p3 = cmp (); + const int *const *const p4 = cmp (); + double (*const p5)(void) = n1; + p2 = _Generic(0, int : nullptr); + p3 = nullptr; + /* -- the left operand is an atomic, qualified, or unqualified bool, and + the type of the right is nullptr_t; */ + _Bool b1; + b1 = cmp (); + const _Bool b2 = nullptr; + _Atomic _Bool b3; + b3 = n1; + (void) b1; + (void) b3; + (void) n3; + (void) n4; + (void) n5; + (void) p2; + (void) p3; + + test_arg1 (nullptr, nullptr, nullptr); + test_arg2 (nullptr, nullptr, nullptr); + test_arg3 (nullptr, nullptr, nullptr); +} + +/* var_arg etc. */ +static void +test5 (int i, ...) +{ + va_list ap; + va_start (ap, i); + if (va_arg (ap, void *)) + __builtin_abort (); +} + +/* Operand of alignas, sizeof or typeof operators. */ +void +test6 (void) +{ + _Static_assert (sizeof (nullptr) == sizeof (void *), "sizeof (nullptr)"); + _Static_assert (sizeof (nullptr_t) == sizeof (void *), "sizeof (nullptr_t)"); + _Static_assert (sizeof (nullptr) == sizeof (char *), "sizeof (nullptr)"); + _Static_assert (sizeof (nullptr_t) == sizeof (char *), "sizeof (nullptr_t)"); + _Static_assert (_Alignof (nullptr_t) == _Alignof (char *), "_Alignof (nullptr_t)"); + __typeof__(nullptr) t = nullptr; + f1 (t); + _Alignas (nullptr_t) char i1 = 'q'; + + _Static_assert (_Generic (nullptr, nullptr_t: 1, default: 0) == 1, "_Generic"); + _Static_assert (_Generic (t, nullptr_t: 1, default: 0) == 1, "_Generic"); + _Static_assert (_Generic (cmp (), nullptr_t: 1, default: 0) == 1, "_Generic"); + _Static_assert (_Generic (0, nullptr_t: 1, int: 2, default: 0) == 2, "_Generic"); + _Static_assert (_Generic ((void *)0, nullptr_t: 1, void *: 2, default: 0) == 2, "_Generic"); + _Static_assert (_Generic (nullptr, nullptr_t: 1, void *: 2, default: 0) == 1, "_Generic"); +} + +/* Play with !, ||, &&. */ +void +test7 (void) +{ + if (nullptr) + __builtin_abort (); + if (1 && nullptr) + __builtin_abort (); + if (0 || nullptr) + __builtin_abort (); + if (nullptr && 1) + __builtin_abort (); + if (nullptr || 0) + __builtin_abort (); + if (!nullptr) + { + } + else + __builtin_abort (); + while (nullptr) + __builtin_abort (); + int i = 0; + do + ++i; + while (nullptr); + if (i != 1) + __builtin_abort (); + for (;nullptr;) + __builtin_abort (); +} + +int +main (void) +{ + int i = 42; + test1 (); + test2 (&i); + test3 (&i, 0); + test4 (); + test5 (42, nullptr); + test6 (); + test7 (); +} diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-2.c b/gcc/testsuite/gcc.dg/c2x-nullptr-2.c new file mode 100644 index 0000000..b610565 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-2.c @@ -0,0 +1,9 @@ +/* Test nullptr_t from <stddef.h>. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include <stddef.h> + +void f(nullptr_t); +_Static_assert (sizeof (nullptr_t) == sizeof (char *), "sizeof (nullptr_t)"); +_Static_assert (_Alignof (nullptr_t) == _Alignof (char *), "_Alignof (nullptr_t)"); diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-3.c b/gcc/testsuite/gcc.dg/c2x-nullptr-3.c new file mode 100644 index 0000000..34e3e03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-3.c @@ -0,0 +1,80 @@ +/* Test wrong usage of C23 nullptr. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wall -Wextra -Wno-unused-variable" } */ + +typedef __typeof__(nullptr) nullptr_t; + +void g (nullptr_t); /* { dg-message "expected .nullptr_t. but argument is of type .int." } */ +nullptr_t cmp (void); + +void +test1 (int *p) +{ + (void) (p > nullptr); /* { dg-error "ordered comparison" } */ + (void) (p >= nullptr); /* { dg-error "ordered comparison" } */ + (void) (p < nullptr); /* { dg-error "ordered comparison" } */ + (void) (p <= nullptr); /* { dg-error "ordered comparison" } */ + (void) (nullptr == 1); /* { dg-error "invalid operands" } */ + (void) (1 == nullptr); /* { dg-error "invalid operands" } */ + (void) (nullptr != 1); /* { dg-error "invalid operands" } */ + (void) (1 != nullptr); /* { dg-error "invalid operands" } */ + (void) (1 > nullptr); /* { dg-error "invalid operands" } */ + + /* "(nullptr_t)nullptr" has type nullptr_t but isn't an NPC. */ + (void) ((nullptr_t)nullptr == p); /* { dg-error "invalid operands" } */ + (void) ((nullptr_t)nullptr != p); /* { dg-error "invalid operands" } */ + (void) (p == (nullptr_t)nullptr); /* { dg-error "invalid operands" } */ + (void) (p != (nullptr_t)nullptr); /* { dg-error "invalid operands" } */ + (void) (cmp () == p); /* { dg-error "invalid operands" } */ + (void) (cmp () != p); /* { dg-error "invalid operands" } */ + (void) (p == cmp ()); /* { dg-error "invalid operands" } */ + (void) (p != cmp ()); /* { dg-error "invalid operands" } */ + /* "(void *)nullptr" is not an NPC, either. */ + (void) ((void *)nullptr == cmp ()); /* { dg-error "invalid operands" } */ + (void) ((void *)nullptr != cmp ()); /* { dg-error "invalid operands" } */ + (void) (cmp () == (void *)nullptr); /* { dg-error "invalid operands" } */ + (void) (cmp () != (void *)nullptr); /* { dg-error "invalid operands" } */ +} + +void +test2 (void) +{ + const nullptr_t nptr = nullptr; + int p = nullptr; /* { dg-error "incompatible types" } */ + float d = nullptr; /* { dg-error "incompatible types" } */ + char arr[10] = { nullptr }; /* { dg-error "incompatible types" } */ + + /* No type other than nullptr_t shall be converted to nullptr_t. */ + const nullptr_t n = 0; /* { dg-error "invalid initializer" } */ + +(nullptr_t) 0; /* { dg-error "conversion from .int. to .nullptr_t." } */ + + g (0); /* { dg-error "incompatible type" } */ + + int i = 42 + nullptr; /* { dg-error "invalid operands" } */ + + /* The assignment of an object of type nullptr_t with a value of another + type, even if the value is a null pointer constant, is a constraint + violation. */ + nullptr_t m; + m = 0; /* { dg-error "incompatible types" } */ + (void) m; + nullptr_t o = 0; /* { dg-error "invalid initializer" } */ + + switch (nullptr); /* { dg-error "switch quantity not an integer" } */ +} + +/* If a second or third operand of type nullptr_t is used that is not a null + pointer constant and the other operand is not a pointer or does not have + itself nullptr_t, a constraint is violated even if that other operand is + a null pointer constant such as 0. */ +void +test3 (_Bool b, int i) +{ + const nullptr_t nptr = nullptr; + __auto_type a1 = b ? nptr : i; /* { dg-error "type mismatch" } */ + __auto_type a2 = b ? i : nptr; /* { dg-error "type mismatch" } */ + __auto_type a3 = b ? nptr : 0; /* { dg-error "type mismatch" } */ + __auto_type a4 = b ? 0 : nptr; /* { dg-error "type mismatch" } */ + __auto_type a5 = b ? 0 : nullptr; /* { dg-error "type mismatch" } */ + __auto_type a6 = b ? nullptr : 0; /* { dg-error "type mismatch" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-4.c b/gcc/testsuite/gcc.dg/c2x-nullptr-4.c new file mode 100644 index 0000000..7479ab4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-4.c @@ -0,0 +1,11 @@ +/* Test that -Wc11-c2x-compat issues a warning (not a pedwarn) about + `nullptr' in C2X. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ + +int * +fn (int *p) +{ + p = nullptr; /* { dg-warning "ISO C does not support .nullptr. before C2X" } */ + return p; +} diff --git a/gcc/testsuite/gcc.dg/c2x-nullptr-5.c b/gcc/testsuite/gcc.dg/c2x-nullptr-5.c new file mode 100644 index 0000000..27803f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-nullptr-5.c @@ -0,0 +1,14 @@ +/* Test that we don't lose side-effects when converting from nullptr_t. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int i; +nullptr_t fn () { ++i; return nullptr; } + +int +main () +{ + int *p = fn (); + if (i != 1) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c b/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c index fc0e778..72bfd56 100644 --- a/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c +++ b/gcc/testsuite/gcc.dg/c2x-old-style-definition-6.c @@ -1,16 +1,16 @@ -/* Test old-style function definitions not in C2x: () does not give - type with a prototype except for function definitions. */ +/* Test old-style function definitions not in C2x: () gives a type with + a prototype for all declarations. */ /* { dg-do compile } */ /* { dg-options "-std=c2x" } */ -void f1 (); +void f1 (); /* { dg-message "declared here" } */ -/* Prototyped function returning a pointer to unprototyped function. */ +/* Prototyped function returning a pointer to a function with no arguments. */ void (*f2 (void))() { return f1; } void g (void) { - f1 (1); - f2 () (1); + f1 (1); /* { dg-error "too many arguments" } */ + f2 () (1); /* { dg-error "too many arguments" } */ } diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-1.c b/gcc/testsuite/gcc.dg/c2x-unproto-1.c index aa87d78..d21c6a7 100644 --- a/gcc/testsuite/gcc.dg/c2x-unproto-1.c +++ b/gcc/testsuite/gcc.dg/c2x-unproto-1.c @@ -1,25 +1,21 @@ -/* Test compatibility of unprototyped and prototyped function types (C2x made - the case of types affected by default argument promotions compatible, before - removing unprototyped functions completely). Test affected usages are not - accepted for C2x. */ +/* Test compatibility of prototyped function types with and without arguments + (C2x made the case of types affected by default argument promotions + compatible, before removing unprototyped functions completely). Test + affected usages are not accepted for C2x. */ /* { dg-do compile } */ /* { dg-options "-std=c2x -pedantic-errors" } */ void f1 (); /* { dg-message "previous declaration" } */ void f1 (float); /* { dg-error "conflicting types" } */ -/* { dg-message "default promotion" "" { target *-*-* } .-1 } */ void f2 (float); /* { dg-message "previous declaration" } */ void f2 (); /* { dg-error "conflicting types" } */ -/* { dg-message "default promotion" "" { target *-*-* } .-1 } */ void f3 (); /* { dg-message "previous declaration" } */ void f3 (char); /* { dg-error "conflicting types" } */ -/* { dg-message "default promotion" "" { target *-*-* } .-1 } */ void f4 (char); /* { dg-message "previous declaration" } */ void f4 (); /* { dg-error "conflicting types" } */ -/* { dg-message "default promotion" "" { target *-*-* } .-1 } */ /* Built-in function case. */ float sqrtf (); /* { dg-warning "conflicting types for built-in function" } */ diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-2.c b/gcc/testsuite/gcc.dg/c2x-unproto-2.c index 3d5ae9d..533fb74 100644 --- a/gcc/testsuite/gcc.dg/c2x-unproto-2.c +++ b/gcc/testsuite/gcc.dg/c2x-unproto-2.c @@ -1,22 +1,18 @@ -/* Test compatibility of unprototyped and prototyped function types (C2x made - the case of types affected by default argument promotions compatible, before - removing unprototyped functions completely). Test always-invalid-in-C2x - usages, in C2X mode. */ +/* Test compatibility of prototyped function types without arguments and with + variable arguments (C2x made the case of types affected by default argument + promotions compatible, before removing unprototyped functions completely). + Test always-invalid-in-C2x usages, in C2X mode. */ /* { dg-do compile } */ /* { dg-options "-std=c2x -pedantic-errors" } */ void f1 (); /* { dg-message "previous declaration" } */ void f1 (int, ...); /* { dg-error "conflicting types" } */ -/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */ void f2 (int, ...); /* { dg-message "previous declaration" } */ void f2 (); /* { dg-error "conflicting types" } */ -/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */ void f3 (); /* { dg-message "previous declaration" } */ void f3 (char, ...); /* { dg-error "conflicting types" } */ -/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */ void f4 (char, ...); /* { dg-message "previous declaration" } */ void f4 (); /* { dg-error "conflicting types" } */ -/* { dg-message "ellipsis" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-3.c b/gcc/testsuite/gcc.dg/c2x-unproto-3.c new file mode 100644 index 0000000..762f8b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-unproto-3.c @@ -0,0 +1,20 @@ +/* Test that declaring a function with () is the same as (void) in C2X. Valid + use cases. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wstrict-prototypes" } */ + +void f1 (); +void f1 (void); + +void f2 (void); +void f2 (); + +typedef void T1 (); +typedef void T1 (void); + +void f3 (); + +_Static_assert (_Generic (f3, + void (*) (int) : 1, + void (*) (void) : 2, + default : 3) == 2); diff --git a/gcc/testsuite/gcc.dg/c2x-unproto-4.c b/gcc/testsuite/gcc.dg/c2x-unproto-4.c new file mode 100644 index 0000000..fceff22 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-unproto-4.c @@ -0,0 +1,15 @@ +/* Test that declaring a function with () is the same as (void) in C2X. + Invalid use cases. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +void f1 (); /* { dg-message "previous declaration" } */ +void f1 (int); /* { dg-error "conflicting types" } */ + +void f2 (); /* { dg-message "declared here" } */ + +void +f3 (void) +{ + f2 (1); /* { dg-error "too many arguments" } */ +} diff --git a/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-1.c b/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-1.c new file mode 100644 index 0000000..45193ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-1.c @@ -0,0 +1,8 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do compile } */ +/* { dg-require-effective-target wchar } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat -pedantic" } */ + +typedef __CHAR32_TYPE__ char32_t; + +const char32_t *a = U"\N{ETHIOPIC SYLLABLE SEE}"; /* { dg-warning "named universal character escapes are only valid in" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-2.c b/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-2.c new file mode 100644 index 0000000..253620a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/named-universal-char-escape-2.c @@ -0,0 +1,8 @@ +/* P2071R2 - Named universal character escapes */ +/* { dg-do compile } */ +/* { dg-require-effective-target wchar } */ +/* { dg-options "-std=gnu99 -Wno-c++-compat -pedantic-errors" } */ + +typedef __CHAR32_TYPE__ char32_t; + +const char32_t *a = U"\N{ETHIOPIC SYLLABLE SEE}"; /* { dg-error "named universal character escapes are only valid in" } */ diff --git a/gcc/testsuite/gcc.dg/darwin-20040809-2.c b/gcc/testsuite/gcc.dg/darwin-20040809-2.c deleted file mode 100644 index 98d5712..0000000 --- a/gcc/testsuite/gcc.dg/darwin-20040809-2.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Test dead code strip support. */ -/* Contributed by Devang Patel <dpatel@apple.com> */ - -/* { dg-do compile { target { *-*-darwin* && stabs } } } */ -/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-symbols" } */ - -int -main () -{ - return 0; -} - -/* { dg-final { scan-assembler ".stabd.46,0,0" } } */ -/* { dg-final { scan-assembler ".stabd.78,0,0" } } */ - diff --git a/gcc/testsuite/gcc.dg/debug/pr35154.c b/gcc/testsuite/gcc.dg/debug/pr35154.c deleted file mode 100644 index 08eefaf..0000000 --- a/gcc/testsuite/gcc.dg/debug/pr35154.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Test to make sure that stabs for C symbols that go into .comm have the - proper structure. These should be lettered G for the struct that gives - the name to the .comm, and should be V or S for .lcomm symbols. */ - -__attribute__ ((used)) -static char i_outer; -struct { - char f1; - char f2; -} opta; -struct { - char f1; - char f2; -} optb; - -int -main() -{ - static char i_inner[2] __attribute__ ((used)); - i_inner[0] = 'a'; i_inner[1] = 'b'; - opta.f1 = 'c'; - opta.f2 = 'd'; - optb.f1 = 'C'; - optb.f2 = 'D'; - i_outer = 'e'; -/* { dg-do compile } */ -/* { dg-skip-if "No stabs" { mmix-*-* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } } */ -/* { dg-skip-if "stabs only" { *-*-* } { "*" } { "-gstabs" } } */ - return 0; -} - -/* { dg-final { scan-assembler ".stabs.*i_inner:V" } } */ -/* { dg-final { scan-assembler ".stabs.*i_outer:S" } } */ -/* { dg-final { scan-assembler ".stabs.*opta:G" } } */ -/* { dg-final { scan-assembler ".stabs.*optb:G" } } */ diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c new file mode 100644 index 0000000..e7dc9df --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c @@ -0,0 +1,29 @@ +/* Test C2X support for empty initializers: valid use cases with GNU + extensions. */ +/* { dg-do run } */ +/* { dg-options "-std=gnu2x" } */ + +extern void exit (int); +extern void abort (void); + +void +f (int a) +{ + struct s { volatile int x[a]; }; + struct s b = {}; + for (int i = 0; i < a; i++) + if (b.x[i] != 0) + abort (); + /* Overwrite contents of b.x before second call to make it more likely stack + contents are nonzero if proper initialization did not occur. */ + for (int i = 0; i < a; i++) + b.x[i] = -1; +} + +int +main (void) +{ + f (100); + f (100); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c new file mode 100644 index 0000000..69ee4e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c @@ -0,0 +1,16 @@ +/* Test C2X support for empty initializers: invalid use cases with GNU + extensions. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu2x" } */ + +void +f (int a) +{ + /* Make sure a non-braced initializer for a VLA-in-struct is still not + allowed. */ + struct s { int x[a]; }; + struct s b; + for (int i = 0; i < a; i++) + b.x[i] = 0; + struct s c = b; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */ +} diff --git a/gcc/testsuite/gcc.dg/init-bad-1.c b/gcc/testsuite/gcc.dg/init-bad-1.c index 6173404..0da10c3 100644 --- a/gcc/testsuite/gcc.dg/init-bad-1.c +++ b/gcc/testsuite/gcc.dg/init-bad-1.c @@ -21,8 +21,7 @@ char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' i char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */ /* { dg-message "near init" "near" { target *-*-* } .-1 } */ -int i = { }; /* { dg-error "empty scalar initializer" } */ -/* { dg-message "near init" "near" { target *-*-* } .-1 } */ +int i = { }; int j = { 1 }; diff --git a/gcc/testsuite/gcc.dg/noncompile/pr71583.c b/gcc/testsuite/gcc.dg/noncompile/pr71583.c index 5045b88..fe6e556 100644 --- a/gcc/testsuite/gcc.dg/noncompile/pr71583.c +++ b/gcc/testsuite/gcc.dg/noncompile/pr71583.c @@ -5,7 +5,7 @@ void f (int i) { (int (*)[++i]) { int }; /* { dg-error "expected" } */ - (int (*)[++i]) { }; /* { dg-error "empty" } */ + (int (*)[++i]) { }; (int (*)[++i]) { , }; /* { dg-error "expected" } */ (int (*)[++i]) { f () }; /* { dg-error "too few" } */ } diff --git a/gcc/testsuite/gcc.dg/pr106099.c b/gcc/testsuite/gcc.dg/pr106099.c new file mode 100644 index 0000000..01b1144 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr106099.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/106099 */ +/* { dg-do compile } */ +/* { dg-options "-O -fharden-compares -fno-tree-forwprop -fno-tree-ch -fno-tree-dominator-opts -fno-tree-ccp -funreachable-traps --param=scev-max-expr-size=1" } */ + +void +foo (void) +{ + for (unsigned i = 0; i == 0; i++) + __builtin_printf ("%d", i); +} diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c index e707904..f41789c 100644 --- a/gcc/testsuite/gcc.dg/pr61096-1.c +++ b/gcc/testsuite/gcc.dg/pr61096-1.c @@ -36,7 +36,7 @@ struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of ini struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */ struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */ -__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */ +__extension__ int a8 = { }; int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */ int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */ __extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */ diff --git a/gcc/testsuite/gcc.dg/pr69471-2.c b/gcc/testsuite/gcc.dg/pr69471-2.c deleted file mode 100644 index d579960..0000000 --- a/gcc/testsuite/gcc.dg/pr69471-2.c +++ /dev/null @@ -1,8 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-gstabs2 -gdwarf-4 -gstabs3" } */ -/* { dg-error "conflicts with prior selectio" "" { target *-*-* } 0 } */ - -void -foo (void) -{ -} diff --git a/gcc/testsuite/gcc.dg/precedence-1.c b/gcc/testsuite/gcc.dg/precedence-1.c index f3f1e35..089cdfc 100644 --- a/gcc/testsuite/gcc.dg/precedence-1.c +++ b/gcc/testsuite/gcc.dg/precedence-1.c @@ -135,10 +135,10 @@ f (void) ASSERT_BIN (0, !=, 2, &, 1, 1, 1, 0); ASSERT_BIN (1, &, 2, ==, 0, 0, 1, 0); ASSERT_BIN (1, &, 2, !=, 0, 1, 0, 1); - ASSERT_BIN (1, &, 2, ^, 3, 3, 3, 1); + ASSERT_BIN (1, &, 0x2, ^, 3, 3, 3, 1); ASSERT_BIN (3, ^, 2, &, 1, 3, 1, 3); ASSERT_BIN (3, ^, 2, |, 1, 1, 1, 0); - ASSERT_BIN (3, |, 2, ^, 1, 3, 2, 3); + ASSERT_BIN (3, |, 0x2, ^, 1, 3, 2, 3); ASSERT_BIN (2, |, 0, &&, 2, 1, 1, 2); ASSERT_BIN (2, &&, 0, |, 2, 1, 2, 1); ASSERT_BIN (0, &&, 0, ||, 1, 1, 1, 0); diff --git a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c new file mode 100644 index 0000000..fddca6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c @@ -0,0 +1,130 @@ +/* { dg-do run } */ +/* { dg-add-options ieee } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#ifndef EXT +int +f1 (void) +{ + return __builtin_issignaling (__builtin_nansf ("")); +} + +int +f2 (void) +{ + return __builtin_issignaling (__builtin_nan ("")); +} + +int +f3 (void) +{ + return __builtin_issignaling (0.0L); +} + +int +f4 (float x) +{ + return __builtin_issignaling (x); +} + +int +f5 (double x) +{ + return __builtin_issignaling (x); +} + +int +f6 (long double x) +{ + return __builtin_issignaling (x); +} +#else +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) + +#if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define FN(F) CONCAT4 (F, f, WIDTH, x) +#else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define FN(F) CONCAT3 (F, f, WIDTH) +#endif + +int +f1 (void) +{ + return __builtin_issignaling (FN (__builtin_nans) ("")); +} + +int +f2 (void) +{ + return __builtin_issignaling (FN (__builtin_nan) ("")); +} + +int +f3 (void) +{ + return __builtin_issignaling (CST (0.0)); +} + +int +f4 (TYPE x) +{ + return __builtin_issignaling (x); +} +#endif + +#ifndef EXT +float x; +double y; +long double z; +#else +TYPE w; +#endif + +int +main () +{ + if (!f1 () || f2 () || f3 ()) + __builtin_abort (); + asm volatile ("" : : : "memory"); +#ifndef EXT + if (f4 (x) || !f4 (__builtin_nansf ("0x123")) || f4 (42.0f) || f4 (__builtin_nanf ("0x234")) + || f4 (__builtin_inff ()) || f4 (-__builtin_inff ()) || f4 (-42.0f) || f4 (-0.0f) || f4 (0.0f)) + __builtin_abort (); + x = __builtin_nansf (""); + asm volatile ("" : : : "memory"); + if (!f4 (x)) + __builtin_abort (); + if (f5 (y) || !f5 (__builtin_nans ("0x123")) || f5 (42.0) || f5 (__builtin_nan ("0x234")) + || f5 (__builtin_inf ()) || f5 (-__builtin_inf ()) || f5 (-42.0) || f5 (-0.0) || f5 (0.0)) + __builtin_abort (); + y = __builtin_nans (""); + asm volatile ("" : : : "memory"); + if (!f5 (y)) + __builtin_abort (); + if (f6 (z) || !f6 (__builtin_nansl ("0x123")) || f6 (42.0L) || f6 (__builtin_nanl ("0x234")) + || f6 (__builtin_infl ()) || f6 (-__builtin_infl ()) || f6 (-42.0L) || f6 (-0.0L) || f6 (0.0L)) + __builtin_abort (); + z = __builtin_nansl (""); + asm volatile ("" : : : "memory"); + if (!f6 (z)) + __builtin_abort (); +#else + if (f4 (w) || !f4 (FN (__builtin_nans) ("0x123")) || f4 (CST (42.0)) || f4 (FN (__builtin_nan) ("0x234")) + || f4 (FN (__builtin_inf) ()) || f4 (-FN (__builtin_inf) ()) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0))) + __builtin_abort (); + w = FN (__builtin_nans) (""); + asm volatile ("" : : : "memory"); + if (!f4 (w)) + __builtin_abort (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-2.c b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-2.c new file mode 100644 index 0000000..4209a21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-2.c @@ -0,0 +1,73 @@ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ +/* { dg-additional-options "-fsignaling-nans" } */ + +int +f1 (void) +{ + return __builtin_issignaling (__builtin_nansd32 ("")); +} + +int +f2 (void) +{ + return __builtin_issignaling (__builtin_nand64 ("")); +} + +int +f3 (void) +{ + return __builtin_issignaling (0.0DD); +} + +int +f4 (_Decimal32 x) +{ + return __builtin_issignaling (x); +} + +int +f5 (_Decimal64 x) +{ + return __builtin_issignaling (x); +} + +int +f6 (_Decimal128 x) +{ + return __builtin_issignaling (x); +} + +_Decimal32 x; +_Decimal64 y; +_Decimal128 z; + +int +main () +{ + if (!f1 () || f2 () || f3 ()) + __builtin_abort (); + asm volatile ("" : : : "memory"); + if (f4 (x) || !f4 (__builtin_nansd32 ("0x123")) || f4 (42.0DF) || f4 (__builtin_nand32 ("0x234")) + || f4 (__builtin_infd32 ()) || f4 (-__builtin_infd32 ()) || f4 (-42.0DF) || f4 (-0.0DF) || f4 (0.0DF)) + __builtin_abort (); + x = __builtin_nansd32 (""); + asm volatile ("" : : : "memory"); + if (!f4 (x)) + __builtin_abort (); + if (f5 (y) || !f5 (__builtin_nansd64 ("0x123")) || f5 (42.0DD) || f5 (__builtin_nand64 ("0x234")) + || f5 (__builtin_infd64 ()) || f5 (-__builtin_infd64 ()) || f5 (-42.0DD) || f5 (-0.0DD) || f5 (0.0DD)) + __builtin_abort (); + y = __builtin_nansd64 (""); + asm volatile ("" : : : "memory"); + if (!f5 (y)) + __builtin_abort (); + if (f6 (z) || !f6 (__builtin_nansd128 ("0x123")) || f6 (42.0DL) || f6 (__builtin_nand128 ("0x234")) + || f6 (__builtin_infd128 ()) || f6 (-__builtin_infd128 ()) || f6 (-42.0DL) || f6 (-0.0DL) || f6 (0.0DL)) + __builtin_abort (); + z = __builtin_nansd128 (""); + asm volatile ("" : : : "memory"); + if (!f6 (z)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c new file mode 100644 index 0000000..7bb903b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-1.c @@ -0,0 +1,115 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +extern void exit (int); +extern void abort (void); +void *memset (void *, int, __SIZE_TYPE__); +int memcmp (const void *, const void *, __SIZE_TYPE__); + +#ifndef TYPE +#define TYPE _Decimal32 +#endif + +#ifndef ZEROFP +#define ZEROFP 0e-101DF +#endif + +TYPE zero_int = 0; +TYPE zero_fp = ZEROFP; +TYPE default_init; +TYPE empty_init = {}; +TYPE zero_bytes; +TYPE x; + +struct s { TYPE a, b; }; +struct s s_default_init; +struct s s_empty_init = {}; +struct s s_first_int = { 0 }; +struct s s_both_int = { 0, 0 }; +struct s sx; + +const TYPE a_default_init[10]; +const TYPE a_empty_init[10] = {}; +const TYPE a_first_int[10] = { 0 }; +const TYPE a_two_int[10] = { 0, 0 }; + +#define CHECK_ZERO_BYTES(expr) \ + do \ + { \ + if (memcmp (expr, &zero_bytes, sizeof zero_bytes) != 0) \ + abort (); \ + TYPE tmp = *expr; \ + if (memcmp (&tmp, &zero_bytes, sizeof zero_bytes) != 0) \ + abort (); \ + } \ + while (0) + +#define CHECK_INT_BYTES(expr) \ + do \ + { \ + if (memcmp (expr, &zero_int, sizeof zero_int) != 0) \ + abort (); \ + TYPE tmp = *expr; \ + if (memcmp (&tmp, &zero_int, sizeof zero_int) != 0) \ + abort (); \ + } \ + while (0) + +int +main (void) +{ + memset (&zero_bytes, 0, sizeof zero_bytes); + if (memcmp (&zero_bytes, &zero_int, sizeof zero_int) == 0) + abort (); + CHECK_ZERO_BYTES (&zero_fp); + CHECK_ZERO_BYTES (&default_init); + CHECK_ZERO_BYTES (&empty_init); + CHECK_ZERO_BYTES (&s_default_init.a); + CHECK_ZERO_BYTES (&s_default_init.b); + CHECK_ZERO_BYTES (&s_empty_init.a); + CHECK_ZERO_BYTES (&s_empty_init.b); + CHECK_INT_BYTES (&s_first_int.a); + CHECK_ZERO_BYTES (&s_first_int.b); + CHECK_INT_BYTES (&s_both_int.a); + CHECK_INT_BYTES (&s_both_int.b); + CHECK_ZERO_BYTES (&a_default_init[0]); + CHECK_ZERO_BYTES (&a_default_init[1]); + CHECK_ZERO_BYTES (&a_default_init[2]); + CHECK_ZERO_BYTES (&a_default_init[9]); + CHECK_ZERO_BYTES (&a_empty_init[0]); + CHECK_ZERO_BYTES (&a_empty_init[1]); + CHECK_ZERO_BYTES (&a_empty_init[2]); + CHECK_ZERO_BYTES (&a_empty_init[9]); + CHECK_INT_BYTES (&a_first_int[0]); + CHECK_ZERO_BYTES (&a_first_int[1]); + CHECK_ZERO_BYTES (&a_first_int[2]); + CHECK_ZERO_BYTES (&a_first_int[9]); + CHECK_INT_BYTES (&a_two_int[0]); + CHECK_INT_BYTES (&a_two_int[1]); + CHECK_ZERO_BYTES (&a_two_int[2]); + CHECK_ZERO_BYTES (&a_two_int[9]); + struct s s2 = {}; + CHECK_ZERO_BYTES (&s2.a); + CHECK_ZERO_BYTES (&s2.b); + struct s s3 = { 0 }; + CHECK_INT_BYTES (&s3.a); + CHECK_ZERO_BYTES (&s3.b); + struct s s4 = { 0, 0 }; + CHECK_INT_BYTES (&s4.a); + CHECK_INT_BYTES (&s4.b); + struct s s5 = { 0 }; + sx = s5; + CHECK_INT_BYTES (&sx.a); + CHECK_ZERO_BYTES (&sx.b); + x = default_init; + CHECK_ZERO_BYTES (&x); + x = zero_int; + CHECK_INT_BYTES (&x); + x = s_default_init.a; + CHECK_ZERO_BYTES (&x); + x = s_default_init.b; + CHECK_ZERO_BYTES (&x); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c new file mode 100644 index 0000000..30f850b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-2.c @@ -0,0 +1,8 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +#define TYPE _Decimal64 +#define ZEROFP 0e-398DD +#include "dfp-default-init-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c b/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c new file mode 100644 index 0000000..cdf7350 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/dfp-default-init-3.c @@ -0,0 +1,8 @@ +/* Test that default-initialized DFP values consistently have the least quantum + exponent. */ +/* { dg-do run } */ +/* { dg-require-effective-target dfp } */ + +#define TYPE _Decimal128 +#define ZEROFP 0e-6176DL +#include "dfp-default-init-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float128-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float128-builtin-issignaling-1.c new file mode 100644 index 0000000..3299ffd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float128 __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float128_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 128 +#define EXT 0 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float128x-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float128x-builtin-issignaling-1.c new file mode 100644 index 0000000..af0b25a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float128x-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float128x __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float128x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float128x_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 128 +#define EXT 1 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float16-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float16-builtin-issignaling-1.c new file mode 100644 index 0000000..a0747e4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float16-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float16 __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float16 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float16_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 16 +#define EXT 0 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float32-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float32-builtin-issignaling-1.c new file mode 100644 index 0000000..38e56c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float32 __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float32_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 32 +#define EXT 0 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float32x-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float32x-builtin-issignaling-1.c new file mode 100644 index 0000000..88eefdb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float32x-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float32x __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float32x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float32x_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 32 +#define EXT 1 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float64-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float64-builtin-issignaling-1.c new file mode 100644 index 0000000..07d755b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float64 __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float64_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 64 +#define EXT 0 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/float64x-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/float64x-builtin-issignaling-1.c new file mode 100644 index 0000000..fe6420a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/float64x-builtin-issignaling-1.c @@ -0,0 +1,13 @@ +/* Test _Float64x __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options float64x } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target float64x_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define WIDTH 64 +#define EXT 1 +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/pr106809.c b/gcc/testsuite/gcc.dg/torture/pr106809.c new file mode 100644 index 0000000..11e1581 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr106809.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Wuninitialized" } */ + +int foo (int x, int *val) +{ + switch (x) + { +#define C(n) \ + case n + 0: return *val; \ + case n + 1: return *val; \ + case n + 2: return *val; \ + case n + 3: return *val; \ + case n + 4: return *val; \ + case n + 5: return *val; \ + case n + 6: return *val; \ + case n + 7: return *val; \ + case n + 8: return *val; \ + case n + 9: return *val; +#define C1(n) \ + C(n+00) C(n+10) C(n+20) C(n+30) C(n+40) \ + C(n+50) C(n+60) C(n+70) C(n+80) C(n+90) +#define C10(n) \ + C1(n+000) C1(n+100) C1(n+200) C1(n+300) C1(n+400) \ + C1(n+500) C1(n+600) C1(n+700) C1(n+800) C1(n+900) + C10(1000) + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr47917.c b/gcc/testsuite/gcc.dg/torture/pr47917.c index 0b45e06..5724907 100644 --- a/gcc/testsuite/gcc.dg/torture/pr47917.c +++ b/gcc/testsuite/gcc.dg/torture/pr47917.c @@ -2,7 +2,6 @@ /* { dg-options "-std=c99" } */ /* { dg-options "-std=gnu99" { target *-*-hpux* } } */ /* { dg-additional-options "-D__USE_MINGW_ANSI_STDIO=1" { target *-*-mingw* } } */ -/* { dg-xfail-run-if "no C99 snprintf function" { *-*-hpux10* } } */ /* { dg-xfail-run-if "non-conforming C99 snprintf" { *-*-hpux11.[012]* } } */ /* PR middle-end/47917 */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c new file mode 100644 index 0000000..8d2d364 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-34.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -fdump-tree-vect-details" } */ +/* { dg-additional-options "-mavx2" { target { x86_64-*-* i?86-*-* } } } */ + +float summul(int n, float *arg1, float *arg2) +{ + int i; + float res1 = 1.0; + for(i = 0; i < n; i++) { + if(arg2[i]) + res1 *= arg1[i]; + } + return res1; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { avr-*-* pru-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c index 5899536..c9322a1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-10.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-optimized" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -16,5 +17,16 @@ uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_max (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "optimized" } } */ /* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c index 1c2ef01..b1da417 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-11.c @@ -1,8 +1,10 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-optimized" } */ #include <stdint.h> + +__attribute__ ((noipa, noinline)) uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -16,6 +18,17 @@ uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax1 (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c index 3d0c07d..cb9188f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-12.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noinline, noipa)) uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -16,5 +17,16 @@ uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax3 (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c index c0d0f27..62ba71e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-13.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -15,5 +16,17 @@ uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { } return xk; } + +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 127; + volatile uint8_t xc = 0; + if (three_minmax2 (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c index 9c0cadb..a3ec584 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-14.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-optimized" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -16,6 +17,17 @@ uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax11 (xc, xm, xy) != 128) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c index 1d97a16..8a39871 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-15.c @@ -1,10 +1,11 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> #include <stdbool.h> -uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy, bool m) { +__attribute__ ((noinline, noipa)) +uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc) { @@ -17,5 +18,17 @@ uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy, bool m) { return xk; } + +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_min (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c index 89377a2..4febd09 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-16.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt -g" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc < xm) { @@ -13,5 +14,16 @@ uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_min (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c index de3b2e9..2af1077 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-3.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc < xm) { @@ -13,5 +14,16 @@ uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_min (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c index 0b6d667..973f39b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-4.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc > xm) { @@ -13,5 +14,16 @@ uint8_t three_max (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_max (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c index 650601a..34e4e72 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-5.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc > xm) { @@ -13,5 +14,16 @@ uint8_t three_minmax1 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax1 (xc, xm, xy) != 127) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c index a628f6d..443d68f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-6.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc > xm) { @@ -13,5 +14,16 @@ uint8_t three_minmax3 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax3 (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c index cb42412..7e2a3f0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-7.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc > xm) { @@ -12,5 +13,17 @@ uint8_t three_minmax2 (uint8_t xc, uint8_t xm, uint8_t xy) { } return xk; } + +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax2 (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 1 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c index 9cd050e..0160e57 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-8.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-phiopt" } */ #include <stdint.h> +__attribute__ ((noinline, noipa)) uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; if (xc < xm) { @@ -13,5 +14,16 @@ uint8_t three_minmax11 (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_minmax11 (xc, xm, xy) != 255) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "MIN_EXPR" 1 "phiopt1" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c index 24f5802..0cfb658 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/minmax-9.c @@ -1,8 +1,9 @@ -/* { dg-do compile } */ +/* { dg-do run } */ /* { dg-options "-O -fdump-tree-optimized" } */ #include <stdint.h> +__attribute__ ((noipa, noinline)) uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { uint8_t xk; xc=~xc; @@ -16,5 +17,16 @@ uint8_t three_min (uint8_t xc, uint8_t xm, uint8_t xy) { return xk; } +int +main (void) +{ + volatile uint8_t xy = 255; + volatile uint8_t xm = 0; + volatile uint8_t xc = 127; + if (three_min (xc, xm, xy) != 0) + __builtin_abort (); + return 0; +} + /* { dg-final { scan-tree-dump-times "= ~" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr106819.c b/gcc/testsuite/gcc.dg/tree-ssa/pr106819.c new file mode 100644 index 0000000..1272d4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr106819.c @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp-details" } + +static int isNaN(double x) +{ + return x != x; +} + +static double opCmpProper(int lhs, double rhs) +{ + return lhs < rhs ? -1.0 + : lhs > rhs ? 1.0 + : lhs == rhs ? 0.0 + : __builtin_nan(""); +} + +int main() +{ + if (!isNaN(opCmpProper(41, __builtin_nan("")))) + __builtin_abort(); + return 0; +} + +// { dg-final {scan-tree-dump-not "Folds to: 0.0" "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c index 410b280..036f32a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c @@ -1,6 +1,11 @@ /* { dg-do compile } */ /* { dg-options "-O1 -fno-trapping-math -funsafe-math-optimizations -fdump-tree-recip" } */ +/* The recip pass has a threshold of 3 reciprocal operations before it attempts + to optimize a sequence. With a FP enabled ranger, we eliminate one of them + earlier, causing the pass to skip this optimization. */ +/* { dg-additional-options "-fno-thread-jumps -fno-tree-dominator-opts" } */ + double F[5] = { 0.0, 0.0 }, e; /* In this case the optimization is interesting. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-nan-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-nan-1.c new file mode 100644 index 0000000..126949b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-nan-1.c @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-O2 -ffinite-math-only -fdump-tree-evrp" } + +void bar(float); + +void funk(int cond) +{ + float x; + + if (cond) + x = __builtin_nan (""); + else + x = 1.24; + + bar(x); +} + +// { dg-final { scan-tree-dump-times "bar \\(1.24" 1 "evrp" } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-signbit-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-signbit-1.c new file mode 100644 index 0000000..3fa783e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-float-signbit-1.c @@ -0,0 +1,12 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-evrp" } + +int num; + +void func(float x) +{ + if (x > 5.0) + num = __builtin_signbit (x); +} + +// { dg-final { scan-tree-dump-times "num = 0;" 1 "evrp" } } diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c index 9d56101..f88ee2d 100644 --- a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c +++ b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c @@ -7,12 +7,12 @@ int main (void) { /* None of the following should pass. */ - int A[1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ - int B[-1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ - int D[1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ - int E[-1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ - int F[-1 >> 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */ - int G[1 << 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */ + int A[1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + int B[-1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + int D[1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + int E[-1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + int F[-1 >> 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + int G[1 << 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ return 0; } diff --git a/gcc/testsuite/gcc.dg/uninit-pr63660.c b/gcc/testsuite/gcc.dg/uninit-pr63660.c new file mode 100644 index 0000000..eab7c74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr63660.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wuninitialized" } */ + +typedef struct +{ + int a; + int b; + int c; + int d; + int e; + int f; + int g; + int h; + int i; + int j; +} X; + +X *XX(int); + +int G(); + +static void F() +{ + X *x; + int m, n; + int xa, xb, xc, xd, xe, xf, xg, xh, xi, xj; + + m = G(); + n = G(); + if ( n & 1 ) xa = G(); + if ( n & 2 ) xb = G(); + if ( n & 4 ) xc = G(); + if ( n & 32 ) xd = G(); + if ( n & 16 ) xe = G(); + if ( n & 64 ) xf = G(); + if ( n & 256 ) xg = G(); + if ( n & 512 ) xh = G(); + if ( n & 1024 ) xi = G(); + if ( n & 2048 ) xj = G(); + + if ( m >= 64 ) return; + x = XX(m); + if ( n & 1 ) x->a = xa; + if ( n & 2 ) x->b = xb; + if ( n & 4 ) x->c = xc; + if ( n & 32 ) x->d = xd; + if ( n & 16 ) x->e = xe; + if ( n & 64 ) x->f = xf; + if ( n & 256 ) x->g = xg; + if ( n & 512 ) x->h = xh; + if ( n & 1024 ) x->i = xi; + if ( n & 2048 ) x->j = xj; /* { dg-bogus "uninitialized" } */ +} + +void H() +{ + F(); +} diff --git a/gcc/testsuite/gcc.dg/uninit-pr65244-1.c b/gcc/testsuite/gcc.dg/uninit-pr65244-1.c new file mode 100644 index 0000000..7c1d910 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr65244-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wuninitialized" } */ + +extern void __attribute__((noreturn)) abort (void); + +int foo (int flag, int val) +{ + int tem; + if (flag) + { + if (val == 0) + abort (); + tem = val; + } + /* large - prevent jump threading */ + __asm__ volatile ("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + if (flag) + return tem; /* { dg-bogus "uninitialized" } */ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/uninit-pr65244-2.c b/gcc/testsuite/gcc.dg/uninit-pr65244-2.c new file mode 100644 index 0000000..a28893c --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pr65244-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-Og -Wuninitialized -ftree-bit-ccp -fno-thread-jumps -fdump-tree-uninit2" } */ + +void exit(int __status) __attribute__ ((__noreturn__)); +int posix_memalign(void **__memptr, __SIZE_TYPE__ __alignment, + __SIZE_TYPE__ __size); + +void *f(void) +{ + void *ptr; + + if (posix_memalign(&ptr, 16, 256) != 0) + exit(1); + + return ptr; /* { dg-bogus "uninitialized" } */ +} + +/* Make sure the uninit pass has something to do, add to the set of + disabled optimizations if not. */ +/* { dg-final { scan-tree-dump "# ptr_. = PHI" "uninit2" } } */ diff --git a/gcc/testsuite/gcc.dg/uninit-pred-11.c b/gcc/testsuite/gcc.dg/uninit-pred-11.c new file mode 100644 index 0000000..734df37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-pred-11.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wmaybe-uninitialized" } */ + +extern unsigned bar (void); +extern void quux (void); +int z; +unsigned foo (unsigned v, int y) +{ + unsigned u; + if (v != 1) + u = bar (); + + // Prevent the "dom" pass from changing the CFG layout based on the inference + // 'if (v != 1) is false then (v != 2) is true'. (Now it would have to + // duplicate the loop in order to do so, which is deemed expensive.) + for (int i = 0; i < 10; i++) + quux (); + + // This variation from uninit-25.c causes compute_control_dep_chain + // to run into a defect but simple_control_dep_chain saves us here + if (y) + z = 1; + if (v != 1) + return u; /* { dg-bogus "may be used uninitialized" } */ + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/uninit-pred-7_a.c b/gcc/testsuite/gcc.dg/uninit-pred-7_a.c index 434d90a..c2ba2a4 100644 --- a/gcc/testsuite/gcc.dg/uninit-pred-7_a.c +++ b/gcc/testsuite/gcc.dg/uninit-pred-7_a.c @@ -23,7 +23,7 @@ int foo (int n, int l, int m, int r) blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */ if ( l ) - blah(v); /* { dg-bogus "uninitialized" "bogus warning" { xfail *-*-* } } */ + blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */ return 0; } diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-1.c new file mode 100644 index 0000000..c1d4ba3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +int a[4], b[4], c[4], d[4]; + +void f1() +{ + a[0] = (b[1] << c[3]) - d[1]; + a[1] = (b[0] << c[2]) - d[0]; + a[2] = (b[3] << c[1]) - d[3]; + a[3] = (b[2] << c[0]) - d[2]; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp2" { target { vect_var_shift && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-10.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-10.c new file mode 100644 index 0000000..e2c86f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-10.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os -fno-tree-loop-vectorize" } */ + +#include "bb-slp-layout-9.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp1" { target { vect_int && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-11.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-11.c new file mode 100644 index 0000000..d9b5349 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-11.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-vectorize" } */ + +int a[4], b[4], c[400], d[400]; + +void f1() +{ + int a0 = a[0] - b[0]; + int a1 = a[1] + b[1]; + int a2 = a[2] - b[2]; + int a3 = a[3] + b[3]; + int b0 = a0; + int b1 = a1; + int b2 = a2; + int b3 = a3; + for (int i = 0; i < 100; ++i) + { + a0 += c[i * 4 + 1]; + a1 += c[i * 4 + 0]; + a2 += c[i * 4 + 3]; + a3 += c[i * 4 + 2]; + b0 ^= d[i * 4 + 3]; + b1 ^= d[i * 4 + 2]; + b2 ^= d[i * 4 + 1]; + b3 ^= d[i * 4 + 0]; + } + a[0] = a0 ^ b0; + a[1] = a1 ^ b1; + a[2] = a2 ^ b2; + a[3] = a3 ^ b3; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 4 "slp1" { target { vect_int && vect_perm } } } } */ +/* { dg-final { scan-tree-dump "duplicating permutation node" "slp1" { target { vect_int && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-12.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-12.c new file mode 100644 index 0000000..3bf48af --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-12.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os -fno-tree-loop-vectorize" } */ + +#include "bb-slp-layout-11.c" + +/* It would be better to keep the original three permutations. */ +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp1" { target { vect_int && { vect_perm && vect_hw_misalign } } xfail { *-*-* } } } } */ +/* { dg-final { scan-tree-dump-not "duplicating permutation node" "slp1" { target { vect_int && { vect_perm && vect_hw_misalign } } xfail { *-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-13.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-13.c new file mode 100644 index 0000000..9669ade --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-13.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +int a[4], b[4], c[4], d[4]; + +void f1() +{ + a[0] = (b[1] << c[3]) - (d[1] >> c[3]); + a[1] = (b[0] << c[2]) - (d[0] >> c[2]); + a[2] = (b[3] << c[1]) - (d[3] >> c[1]); + a[3] = (b[2] << c[0]) - (d[2] >> c[0]); +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp2" { target { vect_var_shift && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-14.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-14.c new file mode 100644 index 0000000..159bb15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-14.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os" } */ + +#include "bb-slp-layout-13.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 2 "slp2" { target { vect_var_shift && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-15.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-15.c new file mode 100644 index 0000000..d87fc1e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-15.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +int a[4], b[4], c[4], d[4]; + +void f1() +{ + a[0] = (b[3] << c[3]) - d[0]; + a[1] = (b[2] << c[2]) - d[2]; + a[2] = (b[1] << c[1]) - d[4]; + a[3] = (b[0] << c[0]) - d[6]; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp2" { target { vect_var_shift && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-16.c new file mode 100644 index 0000000..559583a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-16.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os" } */ + +#include "bb-slp-layout-15.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp2" { target { vect_var_shift && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-17.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-17.c new file mode 100644 index 0000000..f64a2d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-17.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ + +int a[8], b[8]; + +int f1() +{ + a[0] = b[4] + 1; + a[1] = b[5] + 1; + a[2] = b[6] + 1; + a[3] = b[7] + 1; + a[4] = b[0] + 1; + a[5] = b[1] + 1; + a[6] = b[2] + 1; + a[7] = b[3] + 1; +} + +unsigned short c[2], d[2]; +void f2() { + c[0] += d[1]; + c[1] += d[0]; +} + +typedef int v4si __attribute__((vector_size(16))); +void f3(v4si x) { + a[0] = b[1] + x[1]; + a[1] = b[0] + x[3]; +} diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-18.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-18.c new file mode 100644 index 0000000..ff46272 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-18.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float} */ +/* { dg-additional-options "-w -Wno-psabi -ffast-math" } */ + +typedef float v4sf __attribute__((vector_size(sizeof(float)*4))); + +float __attribute__((noipa)) +f(v4sf v0, v4sf v1) +{ + return v0[0]*v1[0]+v0[1]*v1[1]+v0[2]*v1[2]+v0[3]*v1[3]; +} + +/* We are lacking an effective target for .REDUC_PLUS support. */ +/* { dg-final { scan-tree-dump-times "basic block part vectorized" 1 "slp2" { target x86_64-*-* aarch64*-*-* } } } */ +/* { dg-final { scan-tree-dump-not " = VEC_PERM_EXPR" "slp2" { target x86_64-*-* aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c new file mode 100644 index 0000000..f075a83 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-19.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-vectorize" } */ + +extern int a[][4], b[][4], c[][4], d[4], e[4]; +void f() +{ + int t0 = a[0][3]; + int t1 = a[1][3]; + int t2 = a[2][3]; + int t3 = a[3][3]; + int a0 = 0, a1 = 0, a2 = 0, a3 = 0, b0 = 0, b1 = 0, b2 = 0, b3 = 0; + for (int j = 0; j < 100; ++j) + for (int i = 0; i < 400; i += 4) + { + a0 += b[i][3] * t0; + a1 += b[i][2] * t1; + a2 += b[i][1] * t2; + a3 += b[i][0] * t3; + b0 += c[i][3] * t0; + b1 += c[i][2] * t1; + b2 += c[i][1] * t2; + b3 += c[i][0] * t3; + } + d[0] = a0; + d[1] = a1; + d[2] = a2; + d[3] = a3; + e[0] = b0; + e[1] = b1; + e[2] = b2; + e[3] = b3; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp1" { target { vect_int_mult && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-2.c new file mode 100644 index 0000000..f12290b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-2.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os" } */ + +#include "bb-slp-layout-1.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 2 "slp2" { target { vect_var_shift && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-20.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-20.c new file mode 100644 index 0000000..ed7816b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-20.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-vectorize" } */ + +extern int a[][4], b[][4], c[][4], d[4], e[4]; +void f() +{ + int t0 = a[0][3]; + int t1 = a[1][3]; + int t2 = a[2][3]; + int t3 = a[3][3]; + int a0 = 0, a1 = 0, a2 = 0, a3 = 0, b0 = 0, b1 = 0, b2 = 0, b3 = 0; + for (int i = 0; i < 400; i += 4) + { + a0 += b[i][3] * t0; + a1 += b[i][2] * t1; + a2 += b[i][1] * t2; + a3 += b[i][0] * t3; + b0 += c[i][3] * t0; + b1 += c[i][2] * t1; + b2 += c[i][1] * t2; + b3 += c[i][0] * t3; + } + d[0] = a0; + d[1] = a1; + d[2] = a2; + d[3] = a3; + e[0] = b0; + e[1] = b1; + e[2] = b2; + e[3] = b3; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 3 "slp1" { target { vect_int_mult && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-3.c new file mode 100644 index 0000000..82c2720 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +int a[4], b[4], c[4], d[4]; + +void f1() +{ + a[0] = (b[3] << c[3]) - d[3]; + a[1] = (b[2] << c[2]) - d[2]; + a[2] = (b[1] << c[1]) - d[1]; + a[3] = (b[0] << c[0]) - d[0]; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp2" { target { vect_var_shift && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-4.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-4.c new file mode 100644 index 0000000..45bd6c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-4.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os" } */ + +#include "bb-slp-layout-3.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp2" { target { vect_var_shift && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-5.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-5.c new file mode 100644 index 0000000..b59a159 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +int a[4], b[4], c[4]; + +void f1() +{ + a[0] = b[3] - c[3]; + a[1] = b[2] + c[2]; + a[2] = b[1] - c[1]; + a[3] = b[0] + c[0]; +} + +/* { dg-final { scan-tree-dump "absorbing input layouts" "slp2" { target { vect_int && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-6.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-6.c new file mode 100644 index 0000000..06f5308 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-6.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os" } */ + +#include "bb-slp-layout-5.c" + +/* { dg-final { scan-tree-dump "absorbing input layouts" "slp2" { target { vect_int && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-7.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-7.c new file mode 100644 index 0000000..7a20c60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-7.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-vectorize" } */ + +int a[4], b[400]; + +void f1() +{ + for (int i = 0; i < 100; ++i) + { + a[0] += b[i * 4 + 3]; + a[1] += b[i * 4 + 2]; + a[2] += b[i * 4 + 1]; + a[3] += b[i * 4 + 0]; + } +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 2 "slp1" { target { vect_int && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-8.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-8.c new file mode 100644 index 0000000..ef2f0c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-8.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Os -fno-tree-loop-vectorize" } */ + +#include "bb-slp-layout-7.c" + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 1 "slp1" { target { vect_int && { vect_perm && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-layout-9.c b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-9.c new file mode 100644 index 0000000..c841862 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-layout-9.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fno-tree-loop-vectorize" } */ + +int a[4], b[400], c[400], d[40000]; + +void f1() +{ + int a0 = a[0]; + int a1 = a[1]; + int a2 = a[2]; + int a3 = a[3]; + for (int i = 0; i < 100; ++i) + { + a0 ^= c[i * 4 + 0]; + a1 ^= c[i * 4 + 1]; + a2 ^= c[i * 4 + 2]; + a3 ^= c[i * 4 + 3]; + for (int j = 0; j < 100; ++j) + { + a0 += d[i * 400 + j * 4 + 1]; + a1 += d[i * 400 + j * 4 + 0]; + a2 += d[i * 400 + j * 4 + 3]; + a3 += d[i * 400 + j * 4 + 2]; + } + b[i * 4 + 0] = a0; + b[i * 4 + 1] = a1; + b[i * 4 + 2] = a2; + b[i * 4 + 3] = a3; + } + a[0] = a0; + a[1] = a1; + a[2] = a2; + a[3] = a3; +} + +/* { dg-final { scan-tree-dump-times "add new stmt: \[^\\n\\r\]* = VEC_PERM_EXPR" 2 "slp1" { target { vect_int && vect_perm } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr54400.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr54400.c index 6b427aa..8aec209 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-pr54400.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr54400.c @@ -39,5 +39,5 @@ main () } /* We are lacking an effective target for .REDUC_PLUS support. */ -/* { dg-final { scan-tree-dump-times "basic block part vectorized" 3 "slp2" { target x86_64-*-* } } } */ -/* { dg-final { scan-tree-dump-not " = VEC_PERM_EXPR" "slp2" { target x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump-times "basic block part vectorized" 3 "slp2" { target x86_64-*-* aarch64*-*-* } } } */ +/* { dg-final { scan-tree-dump-not " = VEC_PERM_EXPR" "slp2" { target x86_64-*-* aarch64*-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-11b.c b/gcc/testsuite/gcc.dg/vect/slp-11b.c index c4d9ab0..d0b972f 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-11b.c +++ b/gcc/testsuite/gcc.dg/vect/slp-11b.c @@ -44,4 +44,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { { vect_strided4 || vect_perm } && vect_int_mult } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm && vect_int_mult } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_perm && vect_int_mult } xfail vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-18.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-18.c new file mode 100644 index 0000000..c1d3c27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-18.c @@ -0,0 +1,38 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-Ofast -mavx" { target avx_runtime } } */ + + +int A0[4] = {36,39,42,45}; +int B0[4] = {42,42,0,42}; +float A1[8] = {36,39,42,45,43,32,21,12}; +float B1[8] = {42,42,0,42,42,42,0,42}; +double A2[16] = {36,39,42,45,43,32,21,12,23,34,45,56,42,78,89,11}; +double B2[16] = {42,42,0,42,42,42,42,42,42,42,42,42,0,42,42,42}; + +int main () +{ + int i, j; + int res0 = 1; + float res1 = 1.0; + double res2 = 1.0; + + for (i = 0; i < 4; i++) + if (B0[i]) + res0 *= A0[i]; + + for (i = 0; i < 8; i++) + if (B1[i]) + res1 *= A1[i]; + + for (i = 0; i < 16; i++) + if (B2[i]) + res2 *= A2[i]; + /* check results: */ + if (res0 != 63180 || res1 != 1043228160.000000 + ||res2 != 3296728515318523101184.000000) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "vectorized 3 loops" "vect" { target i?86-*-* x86_64-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c index 5042904..cd65fc3 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c @@ -56,3 +56,5 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 8 \(amdgcn\)} "" { target amdgcn*-*-* } 18 } */ +/* { dg-warning {unsupported simdlen 4 \(amdgcn\)} "" { target amdgcn*-*-* } 18 } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c index f89c73a..ffcbf93 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c @@ -50,3 +50,5 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 8 \(amdgcn\)} "" { target amdgcn*-*-* } 18 } */ +/* { dg-warning {unsupported simdlen 4 \(amdgcn\)} "" { target amdgcn*-*-* } 18 } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c index 75ce696..18d6877 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c @@ -43,3 +43,4 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 4 \(amdgcn\)} "" { target amdgcn*-*-* } 15 } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c index debbe77..e9af0b8 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c @@ -46,3 +46,4 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 8 \(amdgcn\)} "" { target amdgcn*-*-* } 17 } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c index 6a098d9..46da496 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c @@ -41,3 +41,4 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 4 \(amdgcn\)} "" { target amdgcn*-*-* } 15 } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c index 1bfd19d..f414285 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c @@ -92,3 +92,5 @@ main () return 0; } +/* { dg-warning {unsupported simdlen 8 \(amdgcn\)} "" { target amdgcn*-*-* } 17 } */ +/* { dg-warning {unsupported simdlen 8 \(amdgcn\)} "" { target amdgcn*-*-* } 24 } */ diff --git a/gcc/testsuite/gcc.dg/vla-init-2.c b/gcc/testsuite/gcc.dg/vla-init-2.c index 19fbffc..f23630a 100644 --- a/gcc/testsuite/gcc.dg/vla-init-2.c +++ b/gcc/testsuite/gcc.dg/vla-init-2.c @@ -7,4 +7,3 @@ const int i = 1; void foo() { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */ -/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.dg/vla-init-3.c b/gcc/testsuite/gcc.dg/vla-init-3.c index 55e1de6..a854f12 100644 --- a/gcc/testsuite/gcc.dg/vla-init-3.c +++ b/gcc/testsuite/gcc.dg/vla-init-3.c @@ -6,4 +6,3 @@ /* { dg-options "" } */ void foo(int i) { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */ -/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c index 285751e..9db9535 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_1.c @@ -12,7 +12,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, /* Initialization. */ svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ - svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */ + svuint8_t init_sve_u2 = {}; svuint8_t init_sve_u3 = { sve_u1 }; svuint8_t init_sve_u4 = { gnu_u1 }; svuint8_t init_sve_u5 = { sve_s1 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'svint8_t'} } */ @@ -31,7 +31,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, /* Compound literals. */ - (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svuint8_t) {}; (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ (svuint8_t) { sve_u1 }; (svuint8_t) { gnu_u1 }; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c index 306fd47..c05b164 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/gnu_vectors_2.c @@ -12,7 +12,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, /* Initialization. */ svuint8_t init_sve_u1 = 0; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ - svuint8_t init_sve_u2 = {}; /* { dg-error {empty scalar initializer} } */ + svuint8_t init_sve_u2 = {}; svuint8_t init_sve_u3 = { sve_u1 }; svuint8_t init_sve_u4 = { gnu_u1 }; svuint8_t init_sve_u5 = { sve_s1 }; @@ -31,7 +31,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, /* Compound literals. */ - (svuint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svuint8_t) {}; (svuint8_t) { 0 }; /* { dg-error {incompatible types when initializing type 'svuint8_t' using type 'int'} } */ (svuint8_t) { sve_u1 }; (svuint8_t) { gnu_u1 }; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c index 7fc51e7..4b34a71 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c @@ -66,14 +66,14 @@ statements (int n) svint8_t init_sve_sc1 = sve_sc1; svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ - svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + svint8_t init_sve_sc3 = {}; int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ /* Compound literals. */ - (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) {}; (svint8_t) { sve_sc1 }; (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c index c575492..34dfd59 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c @@ -66,14 +66,14 @@ statements (int n) svint8_t init_sve_sc1 = sve_sc1; svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ - svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + svint8_t init_sve_sc3 = {}; int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ /* Compound literals. */ - (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) {}; (svint8_t) { sve_sc1 }; (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/slp_15.c b/gcc/testsuite/gcc.target/aarch64/sve/slp_15.c new file mode 100644 index 0000000..23f6d56 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/slp_15.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ + +struct foo +{ + void *handle; + void *arg; +}; + +void +dlinfo_doit (struct foo *args) +{ + __UINTPTR_TYPE__ **l = args->handle; + + *(__UINTPTR_TYPE__ *) args->arg = 0; + *(__UINTPTR_TYPE__ *) args->arg = **l; +} diff --git a/gcc/testsuite/gcc.target/bpf/constant-calls.c b/gcc/testsuite/gcc.target/bpf/constant-calls-1.c index 84612a9..6effc7d 100644 --- a/gcc/testsuite/gcc.target/bpf/constant-calls.c +++ b/gcc/testsuite/gcc.target/bpf/constant-calls-1.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-xfail-if "" { bpf-*-* } } */ typedef void *(*T)(void); f1 () diff --git a/gcc/testsuite/gcc.target/bpf/constant-calls-2.c b/gcc/testsuite/gcc.target/bpf/constant-calls-2.c new file mode 100644 index 0000000..836ab67 --- /dev/null +++ b/gcc/testsuite/gcc.target/bpf/constant-calls-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c89 -O2" } */ + +static void * (*bpf_map_lookup_elem)(void *map, const void *key) = (void *) 666; + +int foo () +{ + char *ret; + + ret = bpf_map_lookup_elem (ret, ret); + if (ret) + return 0; + return 1; +} + +/* { dg-final { scan-assembler "call\t666" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/core-pr106745.c b/gcc/testsuite/gcc.target/bpf/core-pr106745.c new file mode 100644 index 0000000..9d34700 --- /dev/null +++ b/gcc/testsuite/gcc.target/bpf/core-pr106745.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -gbtf -dA -mco-re" } */ + +struct weird +{ + struct + { + int b; + }; + + char x; + + union + { + int a; + int c; + }; +}; + + +int test (struct weird *arg) { + int *x = __builtin_preserve_access_index (&arg->b); + int *y = __builtin_preserve_access_index (&arg->c); + + return *x + *y; +} + + +/* { dg-final { scan-assembler-times "ascii \"0:0:0.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */ +/* { dg-final { scan-assembler-times "ascii \"0:2:1.0\"\[\t \]+\[^\n\]*btf_aux_string" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-pr106721.c b/gcc/testsuite/gcc.target/i386/avx512vl-pr106721.c new file mode 100644 index 0000000..8248d14 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512vl-pr106721.c @@ -0,0 +1,19 @@ +/* PR target/106721 */ +/* { dg-do assemble { target avx512vl } } */ +/* { dg-options "-O3 -mavx512vl" } */ + +typedef __bf16 __m256bf16 __attribute__((__vector_size__(32))); +void (*bar) (__m256bf16, __m256bf16, __m256bf16); +__m256bf16 a; +volatile __bf16 b, c, d, e, f, g, h; + +void +foo (void) +{ + __m256bf16 x[8]; + int i; + for (i = 0; i < 8; i++) + x[i] = (__m256bf16) { b, c, d, e, f, g, h }; + a = x[6]; + bar (x[0], x[6], x[7]); +} diff --git a/gcc/testsuite/gcc.target/i386/builtin-issignaling-1.c b/gcc/testsuite/gcc.target/i386/builtin-issignaling-1.c new file mode 100644 index 0000000..8f170c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/builtin-issignaling-1.c @@ -0,0 +1,80 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fsignaling-nans" } */ + +#if __LDBL_MANT_DIG__ == 64 +union U { struct { unsigned long long m; unsigned short e; } p; long double l; }; +union U zero = { { 0, 0 } }; +union U mzero = { { 0, 0x8000 } }; +union U denorm = { { 42, 0 } }; +union U mdenorm = { { 42, 0x8000 } }; +union U pseudodenorm = { { 0x8000000000000000ULL, 0 } }; +union U mpseudodenorm = { { 0x8000000000000000ULL, 0x8000 } }; +union U pseudodenorm1 = { { 0x8000000000000042ULL, 0 } }; +union U mpseudodenorm1 = { { 0x8000000000000042ULL, 0x8000 } }; +union U pseudoinf = { { 0, 0x7fff } }; +union U mpseudoinf = { { 0, 0xffff } }; +union U pseudonan = { { 42, 0x7fff } }; +union U mpseudonan = { { 42, 0xffff } }; +union U pseudonan1 = { { 0x4000000000000000ULL, 0x7fff } }; +union U mpseudonan1 = { { 0x4000000000000000ULL, 0xffff } }; +union U pseudonan2 = { { 0x4000000000000042ULL, 0x7fff } }; +union U mpseudonan2 = { { 0x4000000000000042ULL, 0xffff } }; +union U inf = { { 0x8000000000000000ULL, 0x7fff } }; +union U minf = { { 0x8000000000000000ULL, 0xffff } }; +union U snan = { { 0x8000000000000042ULL, 0x7fff } }; +union U msnan = { { 0x8000000000000042ULL, 0xffff } }; +union U indefinite = { { 0xc000000000000000ULL, 0x7fff } }; +union U mindefinite = { { 0xc000000000000000ULL, 0xffff } }; +union U qnan = { { 0xc000000000000042ULL, 0x7fff } }; +union U mqnan = { { 0xc000000000000042ULL, 0xffff } }; +union U unnormal = { { 0, 0x42 } }; +union U munnormal = { { 0, 0x8042 } }; +union U unnormal1 = { { 42, 0x42 } }; +union U munnormal1 = { { 42, 0x8042 } }; +union U normal = { { 0x8000000000000000ULL, 0x42 } }; +union U mnormal = { { 0x8000000000000000ULL, 0x8042 } }; +union U normal1 = { { 0x8000000000000042ULL, 0x42 } }; +union U mnormal1 = { { 0x8000000000000042ULL, 0x8042 } }; +#endif + +int +main () +{ +#if __LDBL_MANT_DIG__ == 64 + asm volatile ("" : : : "memory"); + if (__builtin_issignaling (zero.l) + || __builtin_issignaling (mzero.l) + || __builtin_issignaling (denorm.l) + || __builtin_issignaling (mdenorm.l) + || __builtin_issignaling (pseudodenorm.l) + || __builtin_issignaling (mpseudodenorm.l) + || __builtin_issignaling (pseudodenorm1.l) + || __builtin_issignaling (mpseudodenorm1.l) + || !__builtin_issignaling (pseudoinf.l) + || !__builtin_issignaling (mpseudoinf.l) + || !__builtin_issignaling (pseudonan.l) + || !__builtin_issignaling (mpseudonan.l) + || !__builtin_issignaling (pseudonan1.l) + || !__builtin_issignaling (mpseudonan1.l) + || !__builtin_issignaling (pseudonan2.l) + || !__builtin_issignaling (mpseudonan2.l) + || __builtin_issignaling (inf.l) + || __builtin_issignaling (minf.l) + || !__builtin_issignaling (snan.l) + || !__builtin_issignaling (msnan.l) + || __builtin_issignaling (indefinite.l) + || __builtin_issignaling (mindefinite.l) + || __builtin_issignaling (qnan.l) + || __builtin_issignaling (mqnan.l) + || !__builtin_issignaling (unnormal.l) + || !__builtin_issignaling (munnormal.l) + || !__builtin_issignaling (unnormal1.l) + || !__builtin_issignaling (munnormal1.l) + || __builtin_issignaling (normal.l) + || __builtin_issignaling (mnormal.l) + || __builtin_issignaling (normal1.l) + || __builtin_issignaling (mnormal1.l)) + __builtin_abort (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr106704.c b/gcc/testsuite/gcc.target/i386/pr106704.c new file mode 100644 index 0000000..44e052a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106704.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx -O2 -mno-avx2" } */ +/* { dg-final { scan-assembler-times {vblendvps[ \t]+%ymm[0-9]+} 1 } } */ +/* { dg-final { scan-assembler-times {vblendvpd[ \t]+%ymm[0-9]+} 1 } } */ + +#include <immintrin.h> + +__m256 bend_stuff( __m256 a, __m256 b, __m256 mask) +{ + return _mm256_blendv_ps(a, b, mask); +} + +__m256d bend_stuff1( __m256d a, __m256d b, __m256d mask) +{ + return _mm256_blendv_pd(a, b, mask); +} diff --git a/gcc/testsuite/gcc.target/i386/pr106707.c b/gcc/testsuite/gcc.target/i386/pr106707.c new file mode 100644 index 0000000..2e8ebaa --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106707.c @@ -0,0 +1,19 @@ +/* PR target/106707 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-Oz -g -fno-cprop-registers -fno-dce" } */ + +typedef unsigned __attribute__((__vector_size__ (8))) V; + +unsigned __int128 ii; +unsigned x, y; + +V v; + +void +foo (long long a) +{ + long long l = a != x; + int i = __builtin_add_overflow_p (y * ii, 0, 0); + V u = ii < x | v, w = x <= u < i & y <= x / ii; + v = __builtin_shufflevector (v, w, 1, 2) + (V) l; +} diff --git a/gcc/testsuite/gcc.target/i386/pr106742.c b/gcc/testsuite/gcc.target/i386/pr106742.c new file mode 100644 index 0000000..36ac93c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106742.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -mno-sse4 -O1" } */ +typedef __bf16 v8bf __attribute__ ((__vector_size__ (16))); + +v8bf +vec_init_dup_v8bf (__bf16 a1) +{ + return __extension__ (v8bf) { a1, a1, a1, a1, a1, a1, a1, a1 }; +} +/* { dg-final { scan-assembler-times "pinsrw" 1} } */ diff --git a/gcc/testsuite/gcc.target/i386/pr106748.c b/gcc/testsuite/gcc.target/i386/pr106748.c new file mode 100644 index 0000000..6388b1d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106748.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -mavx256-split-unaligned-store -mavx -fpack-struct" } */ + +typedef __bf16 __m256bf16 __attribute__((__vector_size__(32))); +typedef struct { + __m256bf16 _m256bf16[1]; +} YMM_T; + +struct { + YMM_T ymm0; +} fregs; + +__m256bf16 do_test_u3b_0_0; +int do_test_i; + +void +do_test() +{ + (&fregs.ymm0)[do_test_i]._m256bf16[0] = do_test_u3b_0_0; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c index f76d554..52b53b9 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c @@ -36,7 +36,7 @@ __bf16 footest (__bf16 scalar0) short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - __bf16 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */ + __bf16 scalar2_1 = {}; __bf16 scalar2_2 = { glob_bfloat }; __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ @@ -88,7 +88,7 @@ __bf16 footest (__bf16 scalar0) /* Compound literals. */ - (__bf16) {}; /* { dg-error {empty scalar initializer} } */ + (__bf16) {}; (__bf16) { glob_bfloat }; (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ diff --git a/gcc/testsuite/gcc.target/loongarch/attr-model-1.c b/gcc/testsuite/gcc.target/loongarch/attr-model-1.c new file mode 100644 index 0000000..916d715 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/attr-model-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-mexplicit-relocs -mcmodel=normal -O2" } */ +/* { dg-final { scan-assembler-times "%pc64_hi12" 2 } } */ + +#define ATTR_MODEL_TEST +#include "attr-model-test.c" diff --git a/gcc/testsuite/gcc.target/loongarch/attr-model-2.c b/gcc/testsuite/gcc.target/loongarch/attr-model-2.c new file mode 100644 index 0000000..a74c795 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/attr-model-2.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-mexplicit-relocs -mcmodel=extreme -O2" } */ +/* { dg-final { scan-assembler-times "%pc64_hi12" 3 } } */ + +#define ATTR_MODEL_TEST +#include "attr-model-test.c" diff --git a/gcc/testsuite/gcc.target/loongarch/attr-model-diag.c b/gcc/testsuite/gcc.target/loongarch/attr-model-diag.c new file mode 100644 index 0000000..88beede --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/attr-model-diag.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-mexplicit-relocs" } */ + +__thread int x __attribute__((model("extreme"))); /* { dg-error "attribute cannot be specified for thread-local variables" } */ +register int y __asm__("tp") __attribute__((model("extreme"))); /* { dg-error "attribute cannot be specified for register variables" } */ +int z __attribute__((model(114))); /* { dg-error "invalid argument" } */ +int t __attribute__((model("good"))); /* { dg-error "invalid argument" } */ diff --git a/gcc/testsuite/gcc.target/loongarch/attr-model-test.c b/gcc/testsuite/gcc.target/loongarch/attr-model-test.c new file mode 100644 index 0000000..5b61a7a --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/attr-model-test.c @@ -0,0 +1,25 @@ +#ifdef ATTR_MODEL_TEST +int x __attribute__((model("extreme"))); +int y __attribute__((model("normal"))); +int z; + +int +test(void) +{ + return x + y + z; +} + +/* The following will be used for kernel per-cpu storage implemention. */ + +register char *per_cpu_base __asm__("r21"); +static int counter __attribute__((section(".data..percpu"), model("extreme"))); + +void +inc_counter(void) +{ + int *ptr = (int *)(per_cpu_base + (long)&counter); + (*ptr)++; +} +#endif + +int dummy; diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c index 276d73e..6339e83 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */ /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ -/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */ extern void g (void); void diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c index 237821c..a53e75e 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */ /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ -/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */ extern void g (void); void diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c index 9a6e161..0da7bf9 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */ /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ -/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */ extern void g (void); void diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c index 2577e34..0219688 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */ /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ -/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */ extern void g (void); void diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c index d70b6ea..8a47b5a 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */ /* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ /* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ -/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c index f963a99..1e75e60 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */ /* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ /* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ -/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c index f2818b2..9e89085 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c @@ -3,7 +3,7 @@ /* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%got_pc_hi20\\(f\\)\n\tld\.d\t.*%got_pc_lo12\\(f\\)\n\tjirl" } } */ /* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ -/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c index 7fa873d..fde9c6e 100644 --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c @@ -3,7 +3,8 @@ /* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */ /* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ /* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ -/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/loongarch/pr106459.c b/gcc/testsuite/gcc.target/loongarch/pr106459.c new file mode 100644 index 0000000..eb737dc --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/pr106459.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106459 */ + +typedef unsigned int UDItype __attribute__((mode(DI))); +int foo(UDItype x) { + x = x & (((UDItype)(((UDItype)(((UDItype)0x0F << 8) | 0x0F) << (2 * 8)) | + (((UDItype)0x0F << 8) | 0x0F)) + << (4 * 8)) | + (((UDItype)(((UDItype)0x0F << 8) | 0x0F) << (2 * 8)) | + (((UDItype)0x0F << 8) | 0x0F))); + return x; +} diff --git a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c index 3756632..9432c47 100644 --- a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c +++ b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O0 -fno-plt -mcmodel=normal -mexplicit-relocs" } */ -/* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ +/* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */ __attribute__ ((tls_model ("global-dynamic"))) __thread int a; diff --git a/gcc/testsuite/gcc.target/powerpc/pr106017.c b/gcc/testsuite/gcc.target/powerpc/pr106017.c new file mode 100644 index 0000000..46d6c7a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106017.c @@ -0,0 +1,19 @@ +/* PR target/106017 */ +/* { dg-options "-O1 -mdejagnu-cpu=power10" } */ +/* { dg-require-effective-target power10_ok } */ + +/* Make sure we do not flag any errors on the following test cases. */ + +void takeacc(__vector_quad *); +void +foo (void) +{ + __vector_quad arr[4]; + takeacc (arr); +} + +unsigned char * +bar (__vector_quad *a) +{ + return (unsigned char *)a; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c index dcb30e1..018e1cf 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c +++ b/gcc/testsuite/gcc.target/powerpc/pr86731-fwrapv-longlong.c @@ -31,5 +31,5 @@ vector signed long long splats4(void) /* { dg-final { scan-assembler-times {\mvspltis[bhw]\M} 0 } } */ /* { dg-final { scan-assembler-times {\mvsl[bhwd]\M} 0 } } */ -/* { dg-final { scan-assembler-times {\mp?lxv\M|\mlxv\M|\mlxvd2x\M|\mxxspltidp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mp?lxv\M|\mlvx\M|\mlxvd2x\M|\mxxspltidp\M} 2 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c b/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c deleted file mode 100644 index 5c7acf1..0000000 --- a/gcc/testsuite/gcc.target/powerpc/stabs-attrib-vect-darwin.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Test Attribute Vector associated with vector type stabs. */ -/* { dg-do compile { target powerpc*-*-darwin* } } */ -/* { dg-require-effective-target stabs } */ -/* { dg-options "-gstabs+ -fno-eliminate-unused-debug-types -faltivec" } */ - -int main () -{ - vector int vi = { 6,7,8,9 }; - return 0; -} - -/* { dg-final { scan-assembler ".stabs.*vi\:\\(0,\[0-9\]+\\)=\@V" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-1.c b/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-1.c new file mode 100644 index 0000000..3ff7d9d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zbb -mabi=ilp32" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +int foo(int n) +{ + return __builtin_bswap32(n); +} + +/* { dg-final { scan-assembler "rev8" } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-2.c b/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-2.c new file mode 100644 index 0000000..679b34c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbb_32_bswap-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zbb -mabi=ilp32" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +int foo(int n) +{ + return __builtin_bswap16(n); +} + +/* { dg-final { scan-assembler "rev8" } } */ +/* { dg-final { scan-assembler "srli" } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/zbb_bswap-1.c b/gcc/testsuite/gcc.target/riscv/zbb_bswap-1.c new file mode 100644 index 0000000..20feded --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbb_bswap-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zbb -mabi=lp64" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +int foo(int n) +{ + return __builtin_bswap32(n); +} + +/* { dg-final { scan-assembler "rev8" } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/zbb_bswap-2.c b/gcc/testsuite/gcc.target/riscv/zbb_bswap-2.c new file mode 100644 index 0000000..c358f66 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zbb_bswap-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zbb -mabi=lp64" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +int foo(int n) +{ + return __builtin_bswap16(n); +} + +/* { dg-final { scan-assembler "rev8" } } */ +/* { dg-final { scan-assembler "srli" } } */ + diff --git a/gcc/testsuite/gcc.target/s390/20041216-1.c b/gcc/testsuite/gcc.target/s390/20041216-1.c deleted file mode 100644 index 492ee6c..0000000 --- a/gcc/testsuite/gcc.target/s390/20041216-1.c +++ /dev/null @@ -1,23 +0,0 @@ -/* This test case would get an unresolved symbol during link - because stabs referred to an optimized-away literal pool - entry. */ - -/* { dg-do run } */ -/* { dg-options "-O2 -fno-omit-frame-pointer -gstabs" } */ - -int main (void) -{ - static char buf[4096]; - char *p; - - do - { - p = buf; - asm volatile ("" : : : "memory", "0", "1", "2", "3", "4", "5", "6", - "7", "8", "9", "10", "12"); - } - while (*p); - - return 0; -} - diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-copysign.c b/gcc/testsuite/gcc.target/s390/vector/vec-copysign.c index 64c6970..b723ceb 100644 --- a/gcc/testsuite/gcc.target/s390/vector/vec-copysign.c +++ b/gcc/testsuite/gcc.target/s390/vector/vec-copysign.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { s390*-*-* } } } */ -/* { dg-options "-O2 -ftree-vectorize -mzarch" } */ +/* { dg-options "-O2 -ftree-vectorize -mzarch -fno-unroll-loops" } */ /* { dg-final { scan-assembler-times "vgmg" 1 } } */ /* { dg-final { scan-assembler-times "vgmf" 1 } } */ /* { dg-final { scan-assembler-times "vsel" 2 } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-sum-across-no-lower-subreg-1.c b/gcc/testsuite/gcc.target/s390/vector/vec-sum-across-no-lower-subreg-1.c new file mode 100644 index 0000000..8d63e8c --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vec-sum-across-no-lower-subreg-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { s390*-*-* } } } */ +/* { dg-options "-O3 -mzarch -mzvector -march=z15 -fdump-rtl-subreg1" } */ + +/* { dg-final { scan-rtl-dump-times "Skipping mode V2DI for copy lowering" 2 "subreg1" } } */ + +#include <vecintrin.h> + +#define STYPE long long +#define VTYPE __attribute__ ((vector_size (16))) STYPE + +STYPE +foo1 (VTYPE a) +{ + /* { dg-final { scan-assembler-not "vst\t.*" } } */ + /* { dg-final { scan-assembler-not "lg\t.*" } } */ + /* { dg-final { scan-assembler-not "lgr\t.*" } } */ + return a[0] + a[1]; +} diff --git a/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z14.c b/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z14.c new file mode 100644 index 0000000..5c64fac --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z14.c @@ -0,0 +1,87 @@ +/* Make sure that the reverse permute patterns are optimized + correctly. */ +/* { dg-do run { target { s390*-*-* } } } */ +/* { dg-options "-O2 -march=z14 -mzarch -fno-unroll-loops" } */ + +/* { dg-final { scan-assembler-times "vpdi\t" 4 } } */ +/* { dg-final { scan-assembler-times "verllg\t" 2 } } */ + +#include <assert.h> + +__attribute__((noipa)) +void reversel (long long *restrict a, long long *restrict b, int n) +{ + for (int i = 0; i < n; i += 2) + { + a[i + 1] = b[i + 0]; + a[i + 0] = b[i + 1]; + } +} + +__attribute__((noipa)) +void reversed (double *restrict a, double *restrict b, int n) +{ + for (int i = 0; i < n; i += 2) + { + a[i + 1] = b[i + 0]; + a[i + 0] = b[i + 1]; + } +} + +__attribute__((noipa)) +void reversei (unsigned int *restrict a, unsigned int *restrict b, int n) +{ + for (int i = 0; i < n; i += 4) + { + a[i + 3] = b[i + 0]; + a[i + 2] = b[i + 1]; + a[i + 1] = b[i + 2]; + a[i + 0] = b[i + 3]; + } +} + +__attribute__((noipa)) +void reversef (float *restrict a, float *restrict b, int n) +{ + for (int i = 0; i < n; i += 4) + { + a[i + 3] = b[i + 0]; + a[i + 2] = b[i + 1]; + a[i + 1] = b[i + 2]; + a[i + 0] = b[i + 3]; + } +} + +int main() +{ + const int n = 1024; + unsigned int u[n], u2[n]; + long long l[n], l2[n]; + double d[n], d2[n]; + float f[n], f2[n]; + + for (int i = 0; i < n; i++) + { + u[i] = i; + l[i] = i; + d[i] = i; + f[i] = i; + u2[i] = i; + l2[i] = i; + d2[i] = i; + f2[i] = i; + } + + reversei (u2, u, n); + reversel (l2, l, n); + reversed (d2, d, n); + reversef (f2, f, n); + + for (int i = 0; i < n - 16; i++) + { + assert (u[i] == u2[i / (16 / sizeof (u[0])) * (16 / sizeof (u[0])) + 16 / sizeof (u[0]) - 1 - i % (16 / sizeof (u[0]))]); + assert (l[i] == l2[i / (16 / sizeof (l[0])) * (16 / sizeof (l[0])) + 16 / sizeof (l[0]) - 1 - i % (16 / sizeof (l[0]))]); + assert (d[i] == d2[i / (16 / sizeof (d[0])) * (16 / sizeof (d[0])) + 16 / sizeof (d[0]) - 1 - i % (16 / sizeof (d[0]))]); + assert (f[i] == f2[i / (16 / sizeof (f[0])) * (16 / sizeof (f[0])) + 16 / sizeof (f[0]) - 1 - i % (16 / sizeof (f[0]))]); + } +} diff --git a/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z15.c b/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z15.c new file mode 100644 index 0000000..bff5240 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/vector/vperm-rev-z15.c @@ -0,0 +1,118 @@ +/* Make sure that the reverse permute patterns are optimized + correctly. */ +/* { dg-do run { target { s390*-*-* } } } */ +/* { dg-options "-O2 -march=z15 -mzarch -fno-unroll-loops" } */ + +/* { dg-final { scan-assembler-times "vsterg\t" 2 } } */ +/* { dg-final { scan-assembler-times "vsterf" 2 } } */ +/* { dg-final { scan-assembler-times "vstbrq\t" 1 } } */ +/* { dg-final { scan-assembler-times "vperm" 0 } } */ + +#include <assert.h> + +__attribute__((noipa)) +void reversec (char *restrict a, char *restrict b, int n) +{ + for (int i = 0; i < n; i += 16) + { + a[i + 0] = b[i + 15]; + a[i + 1] = b[i + 14]; + a[i + 2] = b[i + 13]; + a[i + 3] = b[i + 12]; + a[i + 4] = b[i + 11]; + a[i + 5] = b[i + 10]; + a[i + 6] = b[i + 9]; + a[i + 7] = b[i + 8]; + a[i + 8] = b[i + 7]; + a[i + 9] = b[i + 6]; + a[i + 10] = b[i + 5]; + a[i + 11] = b[i + 4]; + a[i + 12] = b[i + 3]; + a[i + 13] = b[i + 2]; + a[i + 14] = b[i + 1]; + a[i + 15] = b[i + 0]; + } +} + +__attribute__((noipa)) +void reversel (long long *restrict a, long long *restrict b, int n) +{ + for (int i = 0; i < n; i += 2) + { + a[i + 1] = b[i + 0]; + a[i + 0] = b[i + 1]; + } +} + +__attribute__((noipa)) +void reversed (double *restrict a, double *restrict b, int n) +{ + for (int i = 0; i < n; i += 2) + { + a[i + 1] = b[i + 0]; + a[i + 0] = b[i + 1]; + } +} + +__attribute__((noipa)) +void reversei (unsigned int *restrict a, unsigned int *restrict b, int n) +{ + for (int i = 0; i < n; i += 4) + { + a[i + 3] = b[i + 0]; + a[i + 2] = b[i + 1]; + a[i + 1] = b[i + 2]; + a[i + 0] = b[i + 3]; + } +} + +__attribute__((noipa)) +void reversef (float *restrict a, float *restrict b, int n) +{ + for (int i = 0; i < n; i += 4) + { + a[i + 3] = b[i + 0]; + a[i + 2] = b[i + 1]; + a[i + 1] = b[i + 2]; + a[i + 0] = b[i + 3]; + } +} + +int main() +{ + const int n = 1024; + char c[n], c2[n]; + unsigned int u[n], u2[n]; + long long l[n], l2[n]; + double d[n], d2[n]; + float f[n], f2[n]; + + for (int i = 0; i < n; i++) + { + c[i] = i; + u[i] = i; + l[i] = i; + d[i] = i; + f[i] = i; + c2[i] = i; + u2[i] = i; + l2[i] = i; + d2[i] = i; + f2[i] = i; + } + + reversec (c2, c, n); + reversei (u2, u, n); + reversel (l2, l, n); + reversed (d2, d, n); + reversef (f2, f, n); + + for (int i = 0; i < n - 16; i++) + { + assert (c[i] == c2[i / (16 / sizeof (c[0])) * (16 / sizeof (c[0])) + 16 / sizeof (c[0]) - 1 - i % (16 / sizeof (c[0]))]); + assert (u[i] == u2[i / (16 / sizeof (u[0])) * (16 / sizeof (u[0])) + 16 / sizeof (u[0]) - 1 - i % (16 / sizeof (u[0]))]); + assert (l[i] == l2[i / (16 / sizeof (l[0])) * (16 / sizeof (l[0])) + 16 / sizeof (l[0]) - 1 - i % (16 / sizeof (l[0]))]); + assert (d[i] == d2[i / (16 / sizeof (d[0])) * (16 / sizeof (d[0])) + 16 / sizeof (d[0]) - 1 - i % (16 / sizeof (d[0]))]); + assert (f[i] == f2[i / (16 / sizeof (f[0])) * (16 / sizeof (f[0])) + 16 / sizeof (f[0]) - 1 - i % (16 / sizeof (f[0]))]); + } +} diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c index 7c9b20f..8948be2 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c +++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-quiet-uneq.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -march=z13 -mzvector -mzarch" } */ +/* { dg-options "-O3 -march=z13 -mzvector -mzarch -fno-unroll-loops" } */ #include "autovec.h" diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c index 9dfae8f..9417b0c 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c +++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-double-signaling-ltgt.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */ +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-loops" } */ #include "autovec.h" diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c index 5ab9337..0a2aca0 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c +++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-quiet-uneq.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */ +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-loops" } */ #include "autovec.h" diff --git a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c index c34cf09..15e61b7 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c +++ b/gcc/testsuite/gcc.target/s390/zvector/autovec-float-signaling-ltgt.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -march=z14 -mzvector -mzarch" } */ +/* { dg-options "-O3 -march=z14 -mzvector -mzarch -fno-unroll-loops" } */ #include "autovec.h" diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c new file mode 100644 index 0000000..dff3a94 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-int-long.c @@ -0,0 +1,31 @@ +/* Test that we use vpdi in order to reverse vectors + with two elements instead of creating a literal-pool entry + and permuting with vperm. */ +/* { dg-do compile { target { s390*-*-* } } } */ +/* { dg-options "-O2 -march=z14 -mzarch -mzvector -fno-unroll-loops" } */ + +/* { dg-final { scan-assembler-times "vpdi\t" 4 } } */ +/* { dg-final { scan-assembler-times "verllg\t" 2 } } */ +/* { dg-final { scan-assembler-times "vperm" 0 } } */ + +#include <vecintrin.h> + +vector double reved (vector double a) +{ + return vec_reve (a); +} + +vector long long revel (vector long long a) +{ + return vec_reve (a); +} + +vector float revef (vector float a) +{ + return vec_reve (a); +} + +vector int revei (vector int a) +{ + return vec_reve (a); +} diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-reve-store-byte.c b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-store-byte.c index db8284b..6c061c6 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec-reve-store-byte.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-reve-store-byte.c @@ -16,13 +16,11 @@ bar (signed char *target, vector signed char x) vec_xst (vec_reve (x), 0, target); } -/* { dg-final { scan-assembler-times "vstbrq\t" 2 } } */ - -/* mem -> mem: This becomes vlbrq + vst */ +/* mem -> mem: This becomes vl + vstbrq */ void baz (vector signed char *target, vector signed char *x) { *target = vec_reve (*x); } -/* { dg-final { scan-assembler-times "vlbrq\t" 1 } } */ +/* { dg-final { scan-assembler-times "vstbrq\t" 3 } } */ diff --git a/gcc/testsuite/gdc.test/compilable/aliasassign.d b/gcc/testsuite/gdc.test/compilable/aliasassign.d index a29836e..8643f5d 100644 --- a/gcc/testsuite/gdc.test/compilable/aliasassign.d +++ b/gcc/testsuite/gdc.test/compilable/aliasassign.d @@ -3,18 +3,18 @@ template AliasSeq(T...) { alias AliasSeq = T; } template Unqual(T) { static if (is(T U == const U)) - alias Unqual = U; + alias Unqual = U; else static if (is(T U == immutable U)) - alias Unqual = U; + alias Unqual = U; else - alias Unqual = T; + alias Unqual = T; } template staticMap(alias F, T...) { alias A = AliasSeq!(); static foreach (t; T) - A = AliasSeq!(A, F!t); // what's tested + A = AliasSeq!(A, F!t); // what's tested alias staticMap = A; } @@ -28,7 +28,7 @@ template reverse(T...) { alias A = AliasSeq!(); static foreach (t; T) - A = AliasSeq!(t, A); // what's tested + A = AliasSeq!(t, A); // what's tested alias reverse = A; } @@ -38,3 +38,98 @@ alias TK2 = reverse!(int, const uint, X2); static assert(TK2[0] == 3); static assert(is(TK2[1] == const(uint))); static assert(is(TK2[2] == int)); + +/**************************************************/ + +template Tp(Args...) +{ + alias Tp = AliasSeq!(int, 1, "asd", Args); + static foreach (arg; Args) + { + Tp = AliasSeq!(4, Tp, "zxc", arg, Tp, 5, 4, int, Tp[0..2]); + } +} + +void fun(){} + +alias a1 = Tp!(char[], fun, x => x); +static assert( + __traits(isSame, a1, AliasSeq!(4, 4, 4, int, 1, "asd", char[], fun, + x => x, "zxc", char[], int, 1, "asd", char[], fun, x => x, + 5, 4, int, int, 1, "zxc", fun, 4, int, 1, "asd", char[], + fun, x => x, "zxc", char[], int, 1, "asd", char[], fun, + x => x, 5, 4, int, int, 1, 5, 4, int, 4, int, "zxc", x => x, + 4, 4, int, 1, "asd", char[], fun, x => x, "zxc", char[], + int, 1, "asd", char[], fun, x => x, 5, 4, int, int, 1, + "zxc", fun, 4, int, 1, "asd", char[], fun, x => x, "zxc", + char[], int, 1, "asd", char[], fun, x => x, 5, 4, int, int, + 1, 5, 4, int, 4, int, 5, 4, int, 4, 4))); + +template Tp2(Args...) +{ + alias Tp2 = () => 1; + static foreach (i; 0..Args.length) + Tp2 = AliasSeq!(Tp2, Args[i]); +} + +const x = 8; +static assert( + __traits(isSame, Tp2!(2, float, x), AliasSeq!(() => 1, 2, float, x))); + + +enum F(int i) = i * i; + +template staticMap2(alias fun, args...) +{ + alias staticMap2 = AliasSeq!(); + static foreach (i; 0 .. args.length) + staticMap2 = AliasSeq!(fun!(args[i]), staticMap2, fun!(args[i])); +} + +enum a2 = staticMap2!(F, 0, 1, 2, 3, 4); + +struct Cmp(T...){} +// isSame sucks +static assert(is(Cmp!a2 == Cmp!(16, 9, 4, 1, 0, 0, 1, 4, 9, 16))); + +template Tp3() +{ + alias aa1 = int; + static foreach (t; AliasSeq!(float, char[])) + aa1 = AliasSeq!(aa1, t); + static assert(is(aa1 == AliasSeq!(int, float, char[]))); + + alias aa2 = AliasSeq!int; + static foreach (t; AliasSeq!(float, char[])) + aa2 = AliasSeq!(aa2, t); + static assert(is(aa2 == AliasSeq!(int, float, char[]))); + + alias aa3 = AliasSeq!int; + aa3 = AliasSeq!(float, char); + static assert(is(aa3 == AliasSeq!(float, char))); +} +alias a3 = Tp3!(); + +template Tp4() // Uses slow path because overload +{ + alias AliasSeq(T...) = T; + alias AliasSeq(alias f, T...) = T; + + alias aa4 = int; + aa4 = AliasSeq!(aa4, float); + static assert(is(aa4 == AliasSeq!(int, float))); + +} +alias a4 = Tp4!(); + +template Tp5() // same tp overloaded, still uses fast path +{ + alias AliasSeq2(T...) = T; + alias AliasSeq = AliasSeq2; + alias AliasSeq = AliasSeq2; + + alias aa5 = int; + aa5 = AliasSeq!(aa5, float); + static assert(is(aa5 == AliasSeq!(int, float))); +} +alias a5 = Tp5!(); diff --git a/gcc/testsuite/gdc.test/compilable/scope_infer_array_assign.d b/gcc/testsuite/gdc.test/compilable/scope_infer_array_assign.d new file mode 100644 index 0000000..8ef54a1 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/scope_infer_array_assign.d @@ -0,0 +1,28 @@ +// REQUIRED_ARGS: -preview=dip1000 + +// Test that scope inference works even with non POD array assignment +// This is tricky because it gets lowered to something like: +// (S[] __assigntmp0 = e[]) , _d_arrayassign_l(this.e[], __assigntmp0) , this.e[]; + +@safe: + +struct File +{ + void* f; + ~this() scope { } +} + +struct Vector +{ + File[] e; + + auto assign(File[] e) + { + this.e[] = e[]; // slice copy + } +} + +void test(scope File[] arr, Vector v) +{ + v.assign(arr); +} diff --git a/gcc/testsuite/gdc.test/compilable/test21197.d b/gcc/testsuite/gdc.test/compilable/test21197.d new file mode 100644 index 0000000..01ee66e --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test21197.d @@ -0,0 +1,25 @@ +/* REQUIRED_ARGS: -preview=dip1000 + */ +// https://issues.dlang.org/show_bug.cgi?id=21197 + +@safe void check2() +{ + int random; + + S create1() return scope { + return S(); + } + + scope S gen1 = create1; + + S create2() { + return S(&random); + } + + scope S gen2 = create2; +} + +struct S +{ + int* r; +} diff --git a/gcc/testsuite/gdc.test/compilable/uda.d b/gcc/testsuite/gdc.test/compilable/uda.d index ac66c2f..aa6277b 100644 --- a/gcc/testsuite/gdc.test/compilable/uda.d +++ b/gcc/testsuite/gdc.test/compilable/uda.d @@ -6,3 +6,9 @@ struct foo { } @foo bar () { } /************************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=23241 + +alias feynman = int; +enum get = __traits(getAttributes, feynman); +static assert(get.length == 0); diff --git a/gcc/testsuite/gdc.test/fail_compilation/aliasassign2.d b/gcc/testsuite/gdc.test/fail_compilation/aliasassign2.d new file mode 100644 index 0000000..dd421c9 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/aliasassign2.d @@ -0,0 +1,33 @@ +/* TEST_OUTPUT: +--- +fail_compilation/aliasassign2.d(16): Error: `alias aa1 = aa1;` cannot alias itself, use a qualified name to create an overload set +fail_compilation/aliasassign2.d(19): Error: template instance `aliasassign2.Tp1!()` error instantiating +fail_compilation/aliasassign2.d(24): Error: undefined identifier `unknown` +fail_compilation/aliasassign2.d(26): Error: template instance `aliasassign2.Tp2!()` error instantiating +fail_compilation/aliasassign2.d(31): Error: template instance `AliasSeqX!(aa3, 1)` template `AliasSeqX` is not defined, did you mean AliasSeq(T...)? +fail_compilation/aliasassign2.d(33): Error: template instance `aliasassign2.Tp3!()` error instantiating +--- +*/ + +alias AliasSeq(T...) = T; + +template Tp1() +{ + alias aa1 = aa1; + aa1 = AliasSeq!(aa1, float); +} +alias a1 = Tp1!(); + +template Tp2() +{ + alias aa2 = AliasSeq!(); + aa2 = AliasSeq!(aa2, unknown); +} +alias a2 = Tp2!(); + +template Tp3() +{ + alias aa3 = AliasSeq!(); + aa3 = AliasSeqX!(aa3, 1); +} +alias a3 = Tp3!(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23295.d b/gcc/testsuite/gdc.test/fail_compilation/diag23295.d new file mode 100644 index 0000000..a0bfe88 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/diag23295.d @@ -0,0 +1,40 @@ +/* +REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/diag23295.d(21): Error: scope variable `x` assigned to non-scope parameter `y` calling `foo` +fail_compilation/diag23295.d(32): which is assigned to non-scope parameter `z` +fail_compilation/diag23295.d(34): which is not `scope` because of `f = & z` +fail_compilation/diag23295.d(24): Error: scope variable `ex` assigned to non-scope parameter `e` calling `thro` +fail_compilation/diag23295.d(39): which is not `scope` because of `throw e` +--- +*/ + +// explain why scope inference failed +// https://issues.dlang.org/show_bug.cgi?id=23295 + +@safe: + +void main() +{ + scope int* x; + foo(x, null); + + scope Exception ex; + thro(ex); +} + +auto foo(int* y, int** w) +{ + fooImpl(y, null); +} + +auto fooImpl(int* z, int** w) +{ + auto f = &z; +} + +auto thro(Exception e) +{ + throw e; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d index d9f554a..e969b24 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10968.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10968.d @@ -1,26 +1,27 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10968.d(41): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(41): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here fail_compilation/fail10968.d(42): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` fail_compilation/fail10968.d(42): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here fail_compilation/fail10968.d(43): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` fail_compilation/fail10968.d(43): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here -fail_compilation/fail10968.d(46): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(46): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` +fail_compilation/fail10968.d(44): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(44): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.arrayassign._d_arrayassign_l!(SA[], SA)._d_arrayassign_l` fail_compilation/fail10968.d(47): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` fail_compilation/fail10968.d(47): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here -fail_compilation/fail10968.d(47): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor` +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` fail_compilation/fail10968.d(48): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` -fail_compilation/fail10968.d(29): `fail10968.SA.__postblit` is declared here -fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor` +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(48): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arraysetctor!(SA[], SA)._d_arraysetctor` +fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `fail10968.SA.__postblit` +fail_compilation/fail10968.d(49): Error: `@safe` function `fail10968.bar` cannot call `@system` function `fail10968.SA.__postblit` +fail_compilation/fail10968.d(30): `fail10968.SA.__postblit` is declared here +fail_compilation/fail10968.d(49): Error: `pure` function `fail10968.bar` cannot call impure function `core.internal.array.construction._d_arrayctor!(SA[], SA)._d_arrayctor` --- */ @@ -51,12 +52,12 @@ void bar() pure @safe /* TEST_OUTPUT: --- -fail_compilation/fail10968.d(74): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit fail_compilation/fail10968.d(75): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit fail_compilation/fail10968.d(76): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit -fail_compilation/fail10968.d(79): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit +fail_compilation/fail10968.d(77): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit fail_compilation/fail10968.d(80): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit fail_compilation/fail10968.d(81): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit +fail_compilation/fail10968.d(82): Error: struct `fail10968.SD` is not copyable because it has a disabled postblit --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d index be72663..5621ecc 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail14669.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail14669.d @@ -20,9 +20,9 @@ void test1() /* TEST_OUTPUT: --- -fail_compilation/fail14669.d(29): Error: `auto` can only be used as part of `auto ref` for template function parameters +fail_compilation/fail14669.d(29): Error: cannot explicitly instantiate template function with `auto ref` parameter fail_compilation/fail14669.d(38): Error: template instance `fail14669.bar1!int` error instantiating -fail_compilation/fail14669.d(30): Error: `auto` can only be used as part of `auto ref` for template function parameters +fail_compilation/fail14669.d(30): Error: cannot explicitly instantiate template function with `auto ref` parameter fail_compilation/fail14669.d(40): Error: template instance `fail14669.bar2!int` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice8795.d b/gcc/testsuite/gdc.test/fail_compilation/ice8795.d index 5d7d6dd..a30a65b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice8795.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice8795.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` when expecting `(` fail_compilation/ice8795.d-mixin-14(14): Error: expression expected, not `End of File` -fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` when expecting `)` +fail_compilation/ice8795.d-mixin-14(14): Error: missing closing `)` after `switch (0` fail_compilation/ice8795.d-mixin-14(14): Error: found `End of File` instead of statement fail_compilation/ice8795.d-mixin-15(15): Error: { } expected following `interface` declaration fail_compilation/ice8795.d-mixin-15(15): Error: anonymous interfaces not allowed diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/import15525.d b/gcc/testsuite/gdc.test/fail_compilation/imports/import15525.d new file mode 100644 index 0000000..9c05e7c --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/import15525.d @@ -0,0 +1,3 @@ +module imports.import15525; + +template Tuple{ static if } diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue12652.d b/gcc/testsuite/gdc.test/fail_compilation/issue12652.d new file mode 100644 index 0000000..0ddd6b4 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/issue12652.d @@ -0,0 +1,24 @@ +/* +TEST_OUTPUT: +---- +fail_compilation/issue12652.d(18): Error: static initializations of associative arrays is not allowed. +fail_compilation/issue12652.d(18): associative arrays must be initialized at runtime: https://dlang.org/spec/hash-map.html#runtime_initialization +--- +*/ + +enum A +{ + x, + y, + z +} + +struct S +{ + string[A] t = [A.x : "aaa", A.y : "bbb"]; +} + +void main () +{ + S s; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d index a8e5de5..95d5dbe 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d @@ -78,6 +78,7 @@ void foo() @safe fail_compilation/retscope6.d(8016): Error: address of variable `i` assigned to `p` with longer lifetime fail_compilation/retscope6.d(8031): Error: reference to local variable `i` assigned to non-scope parameter `p` calling `betty` fail_compilation/retscope6.d(8031): Error: reference to local variable `j` assigned to non-scope parameter `q` calling `betty` +fail_compilation/retscope6.d(8021): which is assigned to non-scope parameter `p` fail_compilation/retscope6.d(8048): Error: reference to local variable `j` assigned to non-scope parameter `q` calling `archie` --- */ @@ -255,6 +256,7 @@ void escape_throw_20150() @safe /* TEST_OUTPUT: --- fail_compilation/retscope6.d(14019): Error: scope variable `scopePtr` assigned to non-scope parameter `x` calling `noInfer23021` +fail_compilation/retscope6.d(14009): which is not `scope` because of `*escapeHole = cast(const(int)*)x` fail_compilation/retscope6.d(14022): Error: scope variable `scopePtr` may not be returned --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/shared.d b/gcc/testsuite/gdc.test/fail_compilation/shared.d index ab6f540..7d15b16 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/shared.d +++ b/gcc/testsuite/gdc.test/fail_compilation/shared.d @@ -225,3 +225,14 @@ auto ref Object test_inference_4(const return shared ref Object a) { return a; } + +// https://issues.dlang.org/show_bug.cgi?id=23226 +// Allow accessing non-shared `this` +struct BitRange +{ + int bits; + void f() + { + this.bits++; + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15525.d b/gcc/testsuite/gdc.test/fail_compilation/test15525.d new file mode 100644 index 0000000..cd35f30 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test15525.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=15525 + +/* +TEST_OUTPUT: +--- +fail_compilation/imports/import15525.d(3): Error: parenthesized template parameter list expected following template identifier +fail_compilation/imports/import15525.d(3): Error: (expression) expected following `static if` +fail_compilation/imports/import15525.d(3): Error: declaration expected, not `}` +fail_compilation/test15525.d(16): Error: template instance `Tuple!()` template `Tuple` is not defined +--- +*/ + +struct CrashMe +{ + import imports.import15525; + Tuple!() crash; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17423.d b/gcc/testsuite/gdc.test/fail_compilation/test17423.d index 3afb63b..faa9806 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17423.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17423.d @@ -1,7 +1,8 @@ /* REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test17423.d(26): Error: reference to local `this` assigned to non-scope parameter `dlg` calling `opApply` +fail_compilation/test17423.d(27): Error: reference to local `this` assigned to non-scope parameter `dlg` calling `opApply` +fail_compilation/test17423.d(16): which is not `scope` because of `this.myDlg = dlg` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17764.d b/gcc/testsuite/gdc.test/fail_compilation/test17764.d new file mode 100644 index 0000000..6ee988a --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test17764.d @@ -0,0 +1,21 @@ +/* REQUIRED_ARGS: -preview=dip1000 + * TEST_OUTPUT: +--- +fail_compilation/test17764.d(109): Error: scope variable `c` assigned to non-scope `global` +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=17764 + +#line 100 + +int** global; + +struct S { int** str; } + +void f() @safe +{ + int* buf; + S[1] c = S(&buf); + global = c[0].str; /* This should be rejected. */ +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d index 1713c9d..98caa03 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d @@ -2,15 +2,16 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` -fail_compilation/test20245.d(21): Error: copying `&x` into allocated memory escapes a reference to parameter `x` -fail_compilation/test20245.d(22): Error: scope variable `a` may not be returned -fail_compilation/test20245.d(26): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only -fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` -fail_compilation/test20245.d(33): Error: copying `&x` into allocated memory escapes a reference to parameter `x` -fail_compilation/test20245.d(49): Error: reference to local variable `price` assigned to non-scope `this.minPrice` -fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg` calling `this` -fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content` calling `listUp` +fail_compilation/test20245.d(21): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` +fail_compilation/test20245.d(22): Error: copying `&x` into allocated memory escapes a reference to parameter `x` +fail_compilation/test20245.d(23): Error: scope variable `a` may not be returned +fail_compilation/test20245.d(27): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only +fail_compilation/test20245.d(33): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` +fail_compilation/test20245.d(34): Error: copying `&x` into allocated memory escapes a reference to parameter `x` +fail_compilation/test20245.d(50): Error: reference to local variable `price` assigned to non-scope `this.minPrice` +fail_compilation/test20245.d(69): Error: reference to local variable `this` assigned to non-scope parameter `msg` calling `this` +fail_compilation/test20245.d(89): Error: reference to local variable `this` assigned to non-scope parameter `content` calling `listUp` +fail_compilation/test20245.d(82): which is not `scope` because of `charPtr = content` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20809.d b/gcc/testsuite/gdc.test/fail_compilation/test20809.d new file mode 100644 index 0000000..44728c5 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test20809.d @@ -0,0 +1,44 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/test20809.d(114): Deprecation: returning `this.a` escapes a reference to parameter `this` +fail_compilation/test20809.d(112): perhaps annotate the function with `return` +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=20809 + +#line 100 + +@safe: + +struct S +{ + @safe: + int a; + ~this() + { + a = 0; + } + + ref int val() + { + return a; + } +} + +S bar() +{ + return S(2); +} + +int foo() +{ + return bar.val; +} + +void test() +{ + assert(foo() == 2); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23073.d b/gcc/testsuite/gdc.test/fail_compilation/test23073.d new file mode 100644 index 0000000..39106ba --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test23073.d @@ -0,0 +1,35 @@ +/* +REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/test23073.d(28): Error: scope variable `c` assigned to non-scope parameter `c` calling `assignNext` +fail_compilation/test23073.d(22): which is not `scope` because of `c.next = c` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=23073 +// scope inference from pure doesn't consider self-assignment + +@safe: + +class C +{ + C next; +} + +void assignNext(C c) pure nothrow @nogc +{ + c.next = c; +} + +C escape() @nogc +{ + scope C c = new C(); + assignNext(c); + return c.next; +} + +void main() +{ + C dangling = escape(); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/testsemi.d b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d new file mode 100644 index 0000000..fc9bc65 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/testsemi.d @@ -0,0 +1,46 @@ +/* TEST_OUTPUT: +--- +fail_compilation/testsemi.d(102): Error: found `int` when expecting `;` following static assert +fail_compilation/testsemi.d(102): Error: no identifier for declarator `x` +fail_compilation/testsemi.d(109): Error: found `alias` when expecting `;` following alias reassignment +fail_compilation/testsemi.d(112): Error: found `}` when expecting `;` following invariant +fail_compilation/testsemi.d(117): Error: found `int` when expecting `;` following `alias Identifier this` +fail_compilation/testsemi.d(117): Error: no identifier for declarator `x` +fail_compilation/testsemi.d(123): Error: found `int` when expecting `;` following mixin +fail_compilation/testsemi.d(129): Error: found `int` when expecting `;` following `import` Expression +fail_compilation/testsemi.d(131): Error: `}` expected following members in `class` declaration at fail_compilation/testsemi.d(112) +--- + */ + +#line 100 + +static assert(1) +int x; + +template map(alias F, Args...) +{ + alias A = AliasSeq!(); + static foreach (Arg; Args) + A = AliasSeq!(A, F!Arg) + alias staticMap = A; +} + +class C { invariant(3) } + +class D +{ + alias x this + int x; +} + +void test1() +{ + mixin("int x;") + int y; +} + +void test2() +{ + import(1) + int z; +} diff --git a/gcc/testsuite/gdc.test/runnable/test20365.d b/gcc/testsuite/gdc.test/runnable/test20365.d new file mode 100644 index 0000000..71865a5 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test20365.d @@ -0,0 +1,21 @@ +// https://issues.dlang.org/show_bug.cgi?id=20365 + +string result = ""; + +struct S +{ + long[3] a; + this(ref typeof(this)) { result ~= "C"; } +} + +void fun() +{ + S[4] a; + auto b = a; +} + +void main() +{ + fun(); + assert(result == "CCCC"); +} diff --git a/gcc/testsuite/gdc.test/runnable/test20809.d b/gcc/testsuite/gdc.test/runnable/test20809.d new file mode 100644 index 0000000..6d6191e --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test20809.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=20809 + + +@safe: +struct S{ + @safe: + int[8] a; + ~this(){ a[] = 0; } + ref val(){ return a; } +} +S bar(){ return S([2,2,2,2,2,2,2,2]); } +int[8] foo(){ return bar.val; } + +void main(){ assert(foo() == [2,2,2,2,2,2,2,2]); } // error diff --git a/gcc/testsuite/gfortran.dg/PR100136.f90 b/gcc/testsuite/gfortran.dg/PR100136.f90 new file mode 100644 index 0000000..922af4a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100136.f90 @@ -0,0 +1,39 @@ +! { dg-do run } +! { dg-options "-fcheck=pointer" } +! { dg-shouldfail "Argument not allocated" } +! { dg-output "Fortran runtime error: Allocatable actual argument 'c_init2' is not allocated" } +! +! Tests fix for PR100136 +! +! Test cut down from PR58586 +! + +module test_pr58586_mod + implicit none + + type :: a + end type + + type :: c + type(a), allocatable :: a + end type + +contains + + subroutine add_class_c (d) + class(c), value :: d + end subroutine + + class(c) function c_init2() + allocatable :: c_init2 + end function + +end module test_pr58586_mod + +program test_pr58586 + use test_pr58586_mod + + ! This needs to execute, to see whether the segfault at runtime is resolved + call add_class_c(c_init2()) + +end program diff --git a/gcc/testsuite/gfortran.dg/PR100245.f90 b/gcc/testsuite/gfortran.dg/PR100245.f90 new file mode 100644 index 0000000..07c1f7b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/PR100245.f90 @@ -0,0 +1,28 @@ +! { dg-do run } +! +! Test the fix for PR100245 +! + +program main_p + + implicit none + + type :: foo_t + integer :: a + end type foo_t + + integer, parameter :: a = 42 + + class(foo_t), allocatable :: val + class(foo_t), allocatable :: rs1 + type(foo_t), allocatable :: rs2 + + allocate(val, source=foo_t(42)) + if (val%a/=a) stop 1 + rs1 = val + if (rs1%a/=a) stop 2 + rs2 = val + if (rs2%a/=a) stop 3 + deallocate(val, rs1, rs2) + +end program main_p diff --git a/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f b/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f deleted file mode 100644 index 5e5c42e..0000000 --- a/gcc/testsuite/gfortran.dg/debug/pr35154-stabs.f +++ /dev/null @@ -1,35 +0,0 @@ -C Test program for common block debugging. G. Helffrich 11 July 2004. -C { dg-do compile } -C { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } } -C { dg-skip-if "No stabs" { *-*-* } { "*" } { "-gstabs" } } - common i,j - common /label/l,m - i = 1 - j = 2 - k = 3 - l = 4 - m = 5 - call sub - end - subroutine sub - common /label/l,m - logical first - save n - data first /.true./ - if (first) then - n = 0 - first = .false. - endif - n = n + 1 - l = l + 1 - return - end - -C { dg-final { scan-assembler ".stabs.*\"__BLNK__\",226" } } -C { dg-final { scan-assembler ".stabs.*\"i:V.*\",.*,0" } } -C { dg-final { scan-assembler ".stabs.*\"j:V.*\",.*,4" } } -C { dg-final { scan-assembler ".stabs.*\"__BLNK__\",228" } } -C { dg-final { scan-assembler ".stabs.*\"label_\",226" } } -C { dg-final { scan-assembler ".stabs.*\"l:V.*\",.*,0" } } -C { dg-final { scan-assembler ".stabs.*\"m:V.*\",.*,4" } } -C { dg-final { scan-assembler ".stabs.*\"label_\",228" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-parloops.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-parloops.f95 index 96814a1..5dd763f 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-parloops.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-parloops.f95 @@ -29,16 +29,16 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check that exactly one OpenACC kernels construct is analyzed, and that it ! can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is parallelized OpenACC kernels offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized-parloops.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized-parloops.f95 index e858617..eb165e5 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized-parloops.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized-parloops.f95 @@ -33,16 +33,16 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check that exactly one OpenACC kernels construct is analyzed, and that it ! can't be parallelized. ! { dg-final { scan-tree-dump-times "FAILED:" 1 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } ! { dg-final { scan-tree-dump-not "SUCCESS: may be parallelized" "parloops1" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is unparallelized OpenACC kernels offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95 index f8897fc..e8ceda9 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels-unparallelized.f95 @@ -34,16 +34,16 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check that exactly one OpenACC kernels construct is analyzed, and that it ! can't be parallelized. ! { dg-final { scan-tree-dump-times "FAILED:" 1 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } ! { dg-final { scan-tree-dump-not "SUCCESS: may be parallelized" "parloops1" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is unparallelized OpenACC kernels offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95 index 2ed6cdb..7eb7918 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-kernels.f95 @@ -32,16 +32,16 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check that exactly one OpenACC kernels construct is analyzed, and that it ! can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is parallelized OpenACC kernels offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95 index adc3846..8fa1e94 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-parallel.f95 @@ -26,10 +26,10 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc parallel, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC parallel offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc parallel, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95 index 2101587..996b2ae 100644 --- a/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/classify-serial.f95 @@ -29,10 +29,10 @@ program main end program main ! Check the offloaded function's attributes. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint\\)\\)" 1 "ompexp" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc serial, omp target entrypoint, noclone\\)\\)" 1 "ompexp" } } ! Check the offloaded function's classification and compute dimensions (will ! always be 1 x 1 x 1 for non-offloading compilation). ! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC serial offload" 1 "oaccloops" } } ! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccloops" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint\\)\\)" 1 "oaccloops" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(1, 1, 1\\), oacc serial, omp target entrypoint, noclone\\)\\)" 1 "oaccloops" } } diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-2.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-2.f95 index ef53324..8f54db7 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-2.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-2.f95 @@ -34,7 +34,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-2.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-2.f95 index 2f1dcd6..22282ec 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-2.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-2.f95 @@ -40,7 +40,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit-2.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit-2.f95 index 447e85d6..9d057f3 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit-2.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit-2.f95 @@ -40,7 +40,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit.f95 index 4edb288..e0e8564 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-enter-exit.f95 @@ -38,7 +38,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-update.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-update.f95 index fc113e1..5328371 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-update.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data-update.f95 @@ -38,7 +38,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 2 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 2 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data.f95 index 94522f5..da9fe2e 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-data.f95 @@ -38,7 +38,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 3 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 3 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-n.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-n.f95 index b9c4aea..0104c08 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop-n.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop-n.f95 @@ -33,7 +33,7 @@ end module test ! Check that only one loop is analyzed, and that it can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } ! TODO, PR70545. -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" { xfail *-*-* } } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-loop.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-loop.f95 index 6dc7b2e..e3e74e8 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-loop.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-loop.f95 @@ -30,7 +30,7 @@ end program main ! Check that only one loop is analyzed, and that it can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 1 "parloops1" } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 1 "parloops1" } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 1 "parloops1" } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-parallel-loop-data-enter-exit.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-parallel-loop-data-enter-exit.f95 index 48c20b9..5b6ae05 100644 --- a/gcc/testsuite/gfortran.dg/goacc/kernels-parallel-loop-data-enter-exit.f95 +++ b/gcc/testsuite/gfortran.dg/goacc/kernels-parallel-loop-data-enter-exit.f95 @@ -39,7 +39,7 @@ end program main ! Check that only three loops are analyzed, and that all can be parallelized. ! { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops1" { xfail *-*-* } } } -! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint\\)\\)" 2 "parloops1" { xfail *-*-* } } } +! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc kernels parallelized, oacc function \\(, , \\), oacc kernels, omp target entrypoint, noclone\\)\\)" 2 "parloops1" { xfail *-*-* } } } ! { dg-final { scan-tree-dump-not "FAILED:" "parloops1" { xfail *-*-* } } } ! Check that the loop has been split off into a function. diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 index 2eccdf9..d8014d6 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-2.f90 @@ -158,8 +158,8 @@ subroutine foo !$omp do ordered(1) do i = 0, 63 !$omp parallel - !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } - !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } + !$omp ordered depend(source) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } + !$omp ordered depend(sink: i - 1) ! { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause" } !$omp end parallel end do end diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-4.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-4.f90 new file mode 100644 index 0000000..66cf0a3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-4.f90 @@ -0,0 +1,21 @@ +! { dg-do compile } +implicit none +integer ::x,z +x = 42 +print '(*(z16:" "))', loc(x) +!$omp target map(x, z) +block + integer :: y + x = 123 + y = 99 + !$omp target device(ancestor:1) map(always,tofrom:x) map(y) ! { dg-error "'ancestor' device modifier not preceded by 'requires' directive with 'reverse_offload' clause" } + print '(*(z16:" "))', loc(x), loc(y) + print * ,x, y + x = -x + y = -y + !$omp end target ! { dg-error "Unexpected ..OMP END TARGET statement" } + z = y +end block + print * ,x !, z +end + diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90 index ab56e2d..d73adf2 100644 --- a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-4.f90 @@ -6,7 +6,7 @@ !$omp requires reverse_offload -!$omp target device (ancestor : 1) ! { dg-message "sorry, unimplemented: 'ancestor' not yet supported" } +!$omp target device (ancestor : 1) !$omp end target end diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90 index ca8d4b2..9596d61 100644 --- a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90 @@ -17,7 +17,7 @@ contains block block block - !$omp target device(ancestor:1) ! { dg-message "sorry, unimplemented: 'ancestor' not yet supported" } + !$omp target device(ancestor:1) !$omp end target end block end block diff --git a/gcc/testsuite/gfortran.dg/pr103694.f90 b/gcc/testsuite/gfortran.dg/pr103694.f90 new file mode 100644 index 0000000..3ed8b20 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr103694.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! PR fortran/103694 - ICE in gfc_conv_expr_op +! Contributed by G.Steinmetz + +subroutine s + type t + integer :: a(2) + end type + type(t) :: x((0.)/0) + integer :: n = size(x(1)%a) ! { dg-error "does not reduce to a constant expression" } +end diff --git a/gcc/testsuite/gfortran.dg/pr99349.f90 b/gcc/testsuite/gfortran.dg/pr99349.f90 new file mode 100644 index 0000000..e1f4628 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr99349.f90 @@ -0,0 +1,9 @@ +! { dg-do compile } +! PR fortran/99349 - ICE in match_data_constant +! Contributed by G.Steinmetz + +function f() + logical, parameter :: a((1.)/0) = .true. ! { dg-error "Parameter array" } + integer :: b + data b /a%kind/ ! { dg-error "Syntax error" } +end diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index f58b9e6..23ec038 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -656,7 +656,7 @@ proc gcc-dg-target-supports-debug-format { target_compile trivial type } { proc gcc-dg-debug-runtest { target_compile trivial opt_opts testcases } { if ![info exists DEBUG_TORTURE_OPTIONS] { set DEBUG_TORTURE_OPTIONS "" - foreach type {-gctf -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+} { + foreach type {-gctf -gdwarf-2} { if [expr [gcc-dg-target-supports-debug-format \ $target_compile $trivial $type]] { if { $type == "-gctf" } { diff --git a/gcc/testsuite/lib/gfortran-dg.exp b/gcc/testsuite/lib/gfortran-dg.exp index 7407be4..d4a245e 100644 --- a/gcc/testsuite/lib/gfortran-dg.exp +++ b/gcc/testsuite/lib/gfortran-dg.exp @@ -170,7 +170,7 @@ proc gfortran-dg-debug-runtest { target_compile trivial opt_opts testcases } { if ![info exists DEBUG_TORTURE_OPTIONS] { set DEBUG_TORTURE_OPTIONS "" - set type_list [list "-gstabs" "-gstabs+" "-gxcoff" "-gxcoff+" "-gdwarf-2" ] + set type_list [list "-gdwarf-2" ] foreach type $type_list { set comp_output [$target_compile \ "$srcdir/$subdir/$trivial" "trivial.S" assembly \ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 04a2a8e..1de2e8c 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -310,12 +310,6 @@ proc check_weak_available { } { return 1 } - # HP-UX 10.X doesn't support it - - if { [istarget hppa*-*-hpux10*] } { - return 0 - } - # nvptx (nearly) supports it if { [istarget nvptx-*-*] } { @@ -562,8 +556,6 @@ proc check_effective_target_trampolines { } { if { [istarget avr-*-*] || [istarget msp430-*-*] || [istarget nvptx-*-*] - || [istarget hppa2.0w-hp-hpux11.23] - || [istarget hppa64-hp-hpux11.23] || [istarget pru-*-*] || [istarget bpf-*-*] } { return 0; @@ -611,7 +603,7 @@ proc check_effective_target_keeps_null_pointer_checks { } { if [target_info exists keeps_null_pointer_checks] { return 1 } - if { [istarget msp430-*-*] || [istarget cr16-*-*] } { + if { [istarget msp430-*-*] } { return 1; } return 0 @@ -1125,15 +1117,6 @@ proc check_effective_target_pthread {} { } "-pthread"] } -# Return 1 if compilation with -gstabs is error-free for trivial -# code, 0 otherwise. - -proc check_effective_target_stabs {} { - return [check_no_compiler_messages stabs object { - void foo (void) { } - } "-gstabs"] -} - # Return 1 if compilation with -mpe-aligned-commons is error-free # for trivial code, 0 otherwise. @@ -2827,10 +2810,7 @@ proc check_mkfifo_available {} { proc check_cxa_atexit_available { } { return [check_cached_effective_target cxa_atexit_available { - if { [istarget hppa*-*-hpux10*] } { - # HP-UX 10 doesn't have __cxa_atexit but subsequent test passes. - expr 0 - } elseif { [istarget *-*-vxworks] } { + if { [istarget *-*-vxworks] } { # vxworks doesn't have __cxa_atexit but subsequent test passes. expr 0 } else { @@ -6814,6 +6794,7 @@ proc check_effective_target_vect_var_shift { } { return [check_cached_effective_target_indexed vect_var_shift { expr {(([istarget i?86-*-*] || [istarget x86_64-*-*]) && [check_avx2_available]) + || [istarget aarch64*-*-*] }}] } @@ -8646,6 +8627,13 @@ proc check_effective_target_bswap { } { || [istarget powerpc*-*-*] || [istarget rs6000-*-*] || [istarget s390*-*-*] + || ([istarget riscv*-*-*] + && [check_no_compiler_messages_nocache riscv_zbb object { + #if __riscv_zbb <= 0 + #error ZBB is not enabled + #endif + int i; + } ""]) || ([istarget arm*-*-*] && [check_no_compiler_messages_nocache arm_v6_or_later object { #if __ARM_ARCH < 6 diff --git a/gcc/testsuite/objc.dg/stabs-1.m b/gcc/testsuite/objc.dg/stabs-1.m deleted file mode 100644 index b97e4d6..0000000 --- a/gcc/testsuite/objc.dg/stabs-1.m +++ /dev/null @@ -1,19 +0,0 @@ -/* Check if the final SO STABS record goes into the .text section. */ -/* Contributed by Ziemowit Laski <zlaski@apple.com> */ - -/* { dg-do compile { target stabs } } */ -/* { dg-options "-gstabs" } */ -/* { dg-additional-options "-Wno-objc-root-class" } */ - -@interface MyClass -+ newWithArg: arg; -@end - -@implementation MyClass -+ newWithArg: arg -{ -} -@end - -/* See PR target/52152 for the xfail. */ -/* { dg-final { scan-assembler "(.SUBSPA.*\[\$\]CODE\[\$\]|.text\"?)\n\t.stabs.*100,0,0,(\[\.\$\])?L?L\[\$\]?etext\[0-9\]*\n(\[\.\$\])?L?L\[\$\]?etext" { xfail mips*-*-elf* } } } */ diff --git a/gcc/timevar.def b/gcc/timevar.def index 651af19..eac4370 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -176,6 +176,7 @@ DEFTIMEVAR (TV_TREE_SPLIT_EDGES , "tree split crit edges") DEFTIMEVAR (TV_TREE_REASSOC , "tree reassociation") DEFTIMEVAR (TV_TREE_PRE , "tree PRE") DEFTIMEVAR (TV_TREE_FRE , "tree FRE") +DEFTIMEVAR (TV_TREE_RPO_VN , "tree RPO VN") DEFTIMEVAR (TV_TREE_SINK , "tree code sinking") DEFTIMEVAR (TV_TREE_PHIOPT , "tree linearize phis") DEFTIMEVAR (TV_TREE_BACKPROP , "tree backward propagate") diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 61d234a..924871f 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -89,14 +89,6 @@ along with GCC; see the file COPYING3. If not see #include "ipa-param-manipulation.h" #include "dbgcnt.h" -#if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) -#include "dbxout.h" -#endif - -#ifdef XCOFF_DEBUGGING_INFO -#include "xcoffout.h" /* Needed for external data declarations. */ -#endif - #include "selftest.h" #ifdef HAVE_isl @@ -1417,21 +1409,8 @@ process_options (bool no_backend) && ctf_debug_info_level == CTFINFO_LEVEL_NONE) write_symbols = NO_DEBUG; - /* Warn if STABS debug gets enabled and is not the default. */ - if (PREFERRED_DEBUGGING_TYPE != DBX_DEBUG && (write_symbols & DBX_DEBUG)) - warning (0, "STABS debugging information is obsolete and not " - "supported anymore"); - if (write_symbols == NO_DEBUG) ; -#if defined(DBX_DEBUGGING_INFO) - else if (write_symbols == DBX_DEBUG) - debug_hooks = &dbx_debug_hooks; -#endif -#if defined(XCOFF_DEBUGGING_INFO) - else if (write_symbols == XCOFF_DEBUG) - debug_hooks = &xcoff_debug_hooks; -#endif #ifdef DWARF2_DEBUGGING_INFO else if (dwarf_debuginfo_p ()) debug_hooks = &dwarf2_debug_hooks; diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 5bcf781..91ec33c 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -9878,16 +9878,16 @@ execute_fixup_cfg (void) { if (stmt && is_gimple_call (stmt)) gimple_call_set_ctrl_altering (stmt, false); - tree fndecl = builtin_decl_unreachable (); - stmt = gimple_build_call (fndecl, 0); + stmt = gimple_build_builtin_unreachable (UNKNOWN_LOCATION); gimple_stmt_iterator gsi = gsi_last_bb (bb); gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); if (!cfun->after_inlining) - { - gcall *call_stmt = dyn_cast <gcall *> (stmt); - node->create_edge (cgraph_node::get_create (fndecl), - call_stmt, bb->count); - } + if (tree fndecl = gimple_call_fndecl (stmt)) + { + gcall *call_stmt = dyn_cast <gcall *> (stmt); + node->create_edge (cgraph_node::get_create (fndecl), + call_stmt, bb->count); + } } } } diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 86a07c2..80c2bcb 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -345,6 +345,9 @@ enum omp_clause_code { /* OpenMP clause: has_device_addr (variable-list). */ OMP_CLAUSE_HAS_DEVICE_ADDR, + /* OpenMP clause: doacross ({source,sink}:vec). */ + OMP_CLAUSE_DOACROSS, + /* Internal structure to hold OpenACC cache directive's variable-list. #pragma acc cache (variable-list). */ OMP_CLAUSE__CACHE_, @@ -1525,12 +1528,18 @@ enum omp_clause_depend_kind OMP_CLAUSE_DEPEND_INOUT, OMP_CLAUSE_DEPEND_MUTEXINOUTSET, OMP_CLAUSE_DEPEND_INOUTSET, - OMP_CLAUSE_DEPEND_SOURCE, - OMP_CLAUSE_DEPEND_SINK, OMP_CLAUSE_DEPEND_DEPOBJ, + OMP_CLAUSE_DEPEND_INVALID, OMP_CLAUSE_DEPEND_LAST }; +enum omp_clause_doacross_kind +{ + OMP_CLAUSE_DOACROSS_SOURCE, + OMP_CLAUSE_DOACROSS_SINK, + OMP_CLAUSE_DOACROSS_LAST +}; + enum omp_clause_proc_bind_kind { /* Numbers should match omp_proc_bind_t enum in omp.h. */ @@ -1620,6 +1629,7 @@ struct GTY(()) tree_omp_clause { enum omp_clause_default_kind default_kind; enum omp_clause_schedule_kind schedule_kind; enum omp_clause_depend_kind depend_kind; + enum omp_clause_doacross_kind doacross_kind; /* See include/gomp-constants.h for enum gomp_map_kind's values. */ unsigned int map_kind; enum omp_clause_proc_bind_kind proc_bind_kind; diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc index 1c8e1a4..bac29fb 100644 --- a/gcc/tree-if-conv.cc +++ b/gcc/tree-if-conv.cc @@ -1739,6 +1739,7 @@ is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1, if (reduction_op != PLUS_EXPR && reduction_op != MINUS_EXPR + && reduction_op != MULT_EXPR && reduction_op != BIT_IOR_EXPR && reduction_op != BIT_XOR_EXPR && reduction_op != BIT_AND_EXPR) diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc index 9952809..ea7d57a 100644 --- a/gcc/tree-nested.cc +++ b/gcc/tree-nested.cc @@ -1368,6 +1368,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: @@ -2157,6 +2158,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi) case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DOACROSS: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_NUM_TEAMS: case OMP_CLAUSE_THREAD_LIMIT: diff --git a/gcc/tree-parloops.cc b/gcc/tree-parloops.cc index b070527..e4a148b 100644 --- a/gcc/tree-parloops.cc +++ b/gcc/tree-parloops.cc @@ -338,8 +338,8 @@ parloops_is_slp_reduction (loop_vec_info loop_info, gimple *phi, && parloops_valid_reduction_input_p (def_stmt_info)) { if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "swapping oprnds: %G", - next_stmt); + dump_printf_loc (MSG_NOTE, vect_location, + "swapping oprnds: %G", (gimple *) next_stmt); swap_ssa_operands (next_stmt, gimple_assign_rhs1_ptr (next_stmt), @@ -2484,8 +2484,6 @@ transform_to_exit_first_loop_alt (class loop *loop, /* Recalculate dominance info. */ free_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_DOMINATORS); - - checking_verify_ssa (true, true); } /* Tries to moves the exit condition of LOOP to the beginning of its header diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc index 47371d8..33b12c7 100644 --- a/gcc/tree-pretty-print.cc +++ b/gcc/tree-pretty-print.cc @@ -831,34 +831,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case OMP_CLAUSE_DEPEND_INOUTSET: name = "inoutset"; break; - case OMP_CLAUSE_DEPEND_SOURCE: - pp_string (pp, "source)"); - return; case OMP_CLAUSE_DEPEND_LAST: name = "__internal__"; break; - case OMP_CLAUSE_DEPEND_SINK: - pp_string (pp, "sink:"); - for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t)) - if (TREE_CODE (t) == TREE_LIST) - { - dump_generic_node (pp, TREE_VALUE (t), spc, flags, false); - if (TREE_PURPOSE (t) != integer_zero_node) - { - if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t)) - pp_minus (pp); - else - pp_plus (pp); - dump_generic_node (pp, TREE_PURPOSE (t), spc, flags, - false); - } - if (TREE_CHAIN (t)) - pp_comma (pp); - } - else - gcc_unreachable (); - pp_right_paren (pp); - return; default: gcc_unreachable (); } @@ -885,6 +860,49 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) } break; + case OMP_CLAUSE_DOACROSS: + pp_string (pp, OMP_CLAUSE_DOACROSS_DEPEND (clause) + ? "depend(" : "doacross("); + switch (OMP_CLAUSE_DOACROSS_KIND (clause)) + { + case OMP_CLAUSE_DOACROSS_SOURCE: + if (OMP_CLAUSE_DOACROSS_DEPEND (clause)) + pp_string (pp, "source)"); + else + pp_string (pp, "source:)"); + break; + case OMP_CLAUSE_DOACROSS_SINK: + pp_string (pp, "sink:"); + if (OMP_CLAUSE_DECL (clause) == NULL_TREE) + { + pp_string (pp, "omp_cur_iteration-1)"); + break; + } + for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == TREE_LIST) + { + dump_generic_node (pp, TREE_VALUE (t), spc, flags, false); + if (TREE_PURPOSE (t) != integer_zero_node) + { + if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t)) + pp_minus (pp); + else + pp_plus (pp); + dump_generic_node (pp, TREE_PURPOSE (t), spc, flags, + false); + } + if (TREE_CHAIN (t)) + pp_comma (pp); + } + else + gcc_unreachable (); + pp_right_paren (pp); + break; + default: + gcc_unreachable (); + } + break; + case OMP_CLAUSE_MAP: pp_string (pp, "map("); switch (OMP_CLAUSE_MAP_KIND (clause)) diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index d5f2ba8..925bd7d 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -2150,9 +2150,9 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_ gimple_seq stmts = NULL; tree phi_result = PHI_RESULT (phi); result = gimple_build (&stmts, locus, minmax, TREE_TYPE (phi_result), - arg0, bound); + arg0, arg1); result = gimple_build (&stmts, locus, ass_code, TREE_TYPE (phi_result), - result, arg1); + result, bound); if (invert) result = gimple_build (&stmts, locus, BIT_NOT_EXPR, TREE_TYPE (phi_result), result); diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index a1f6f30..74b8d8d 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -4877,41 +4877,44 @@ dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool allow_back) } /* Iterate to the single executable bb2 successor. */ - edge succe = NULL; - FOR_EACH_EDGE (e, ei, bb2->succs) - if ((e->flags & EDGE_EXECUTABLE) - || (!allow_back && (e->flags & EDGE_DFS_BACK))) - { - if (succe) - { - succe = NULL; - break; - } - succe = e; - } - if (succe) + if (EDGE_COUNT (bb2->succs) > 1) { - /* Verify the reached block is only reached through succe. - If there is only one edge we can spare us the dominator - check and iterate directly. */ - if (EDGE_COUNT (succe->dest->preds) > 1) - { - FOR_EACH_EDGE (e, ei, succe->dest->preds) - if (e != succe - && ((e->flags & EDGE_EXECUTABLE) - || (!allow_back && (e->flags & EDGE_DFS_BACK)))) + edge succe = NULL; + FOR_EACH_EDGE (e, ei, bb2->succs) + if ((e->flags & EDGE_EXECUTABLE) + || (!allow_back && (e->flags & EDGE_DFS_BACK))) + { + if (succe) { succe = NULL; break; } - } + succe = e; + } if (succe) { - bb2 = succe->dest; + /* Verify the reached block is only reached through succe. + If there is only one edge we can spare us the dominator + check and iterate directly. */ + if (EDGE_COUNT (succe->dest->preds) > 1) + { + FOR_EACH_EDGE (e, ei, succe->dest->preds) + if (e != succe + && ((e->flags & EDGE_EXECUTABLE) + || (!allow_back && (e->flags & EDGE_DFS_BACK)))) + { + succe = NULL; + break; + } + } + if (succe) + { + bb2 = succe->dest; - /* Re-do the dominance check with changed bb2. */ - if (dominated_by_p (CDI_DOMINATORS, bb1, bb2)) - return true; + /* Re-do the dominance check with changed bb2. */ + if (dominated_by_p (CDI_DOMINATORS, bb1, bb2)) + return true; + } } } @@ -7287,14 +7290,14 @@ eliminate_with_rpo_vn (bitmap inserted_exprs) return walker.eliminate_cleanup (); } -unsigned -do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, - bool iterate, bool eliminate, vn_lookup_kind kind); +static unsigned +do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, + bool iterate, bool eliminate, vn_lookup_kind kind); void run_rpo_vn (vn_lookup_kind kind) { - do_rpo_vn (cfun, NULL, NULL, true, false, kind); + do_rpo_vn_1 (cfun, NULL, NULL, true, false, kind); /* ??? Prune requirement of these. */ constant_to_value_id = new hash_table<vn_constant_hasher> (23); @@ -7992,9 +7995,9 @@ do_unwind (unwind_state *to, rpo_elim &avail) executed and iterate. If ELIMINATE is true then perform elimination, otherwise leave that to the caller. */ -unsigned -do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, - bool iterate, bool eliminate, vn_lookup_kind kind) +static unsigned +do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs, + bool iterate, bool eliminate, vn_lookup_kind kind) { unsigned todo = 0; default_vn_walk_kind = kind; @@ -8412,12 +8415,18 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, /* Region-based entry for RPO VN. Performs value-numbering and elimination on the SEME region specified by ENTRY and EXIT_BBS. If ENTRY is not the only edge into the region at ENTRY->dest PHI nodes in ENTRY->dest - are not considered. */ + are not considered. + If ITERATE is true then treat backedges optimistically as not + executed and iterate. If ELIMINATE is true then perform + elimination, otherwise leave that to the caller. + KIND specifies the amount of work done for handling memory operations. */ unsigned -do_rpo_vn (function *fn, edge entry, bitmap exit_bbs) +do_rpo_vn (function *fn, edge entry, bitmap exit_bbs, + bool iterate, bool eliminate, vn_lookup_kind kind) { - unsigned todo = do_rpo_vn (fn, entry, exit_bbs, false, true, VN_WALKREWRITE); + auto_timevar tv (TV_TREE_RPO_VN); + unsigned todo = do_rpo_vn_1 (fn, entry, exit_bbs, iterate, eliminate, kind); free_rpo_vn (); return todo; } @@ -8473,7 +8482,7 @@ pass_fre::execute (function *fun) if (iterate_p) loop_optimizer_init (AVOID_CFG_MODIFICATIONS); - todo = do_rpo_vn (fun, NULL, NULL, iterate_p, true, VN_WALKREWRITE); + todo = do_rpo_vn_1 (fun, NULL, NULL, iterate_p, true, VN_WALKREWRITE); free_rpo_vn (); if (iterate_p) diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index a1b1e6b..abcf7e6 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -295,8 +295,12 @@ value_id_constant_p (unsigned int v) tree fully_constant_vn_reference_p (vn_reference_t); tree vn_nary_simplify (vn_nary_op_t); -unsigned do_rpo_vn (function *, edge, bitmap, bool, bool, vn_lookup_kind); -unsigned do_rpo_vn (function *, edge, bitmap); +unsigned do_rpo_vn (function *, edge, bitmap, + /* iterate */ bool = false, + /* eliminate */ bool = true, + vn_lookup_kind = VN_WALKREWRITE); + +/* Private interface for PRE. */ void run_rpo_vn (vn_lookup_kind); unsigned eliminate_with_rpo_vn (bitmap); void free_rpo_vn (void); diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index 3218ad9..9725f50 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -719,7 +719,11 @@ back_threader_profitability::possibly_profitable_path_p gimple *stmt = gsi_stmt (gsi); if (gimple_call_internal_p (stmt, IFN_UNIQUE) || gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P)) - return false; + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fputc ('\n', dump_file); + return false; + } /* Do not count empty statements and labels. */ if (gimple_code (stmt) != GIMPLE_NOP && !is_gimple_debug (stmt)) @@ -821,6 +825,8 @@ back_threader_profitability::possibly_profitable_path_p && (m_n_insns * param_fsm_scale_path_stmts >= param_max_jump_thread_duplication_stmts)); + if (dump_file && (dump_flags & TDF_DETAILS)) + fputc ('\n', dump_file); return true; } @@ -947,6 +953,8 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path, "non-empty latch\n"); return false; } + if (dump_file && (dump_flags & TDF_DETAILS)) + fputc ('\n', dump_file); return true; } diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc index 7074c91..29dc48c 100644 --- a/gcc/tree-ssa-uninit.cc +++ b/gcc/tree-ssa-uninit.cc @@ -56,7 +56,8 @@ along with GCC; see the file COPYING3. If not see /* Pointer set of potentially undefined ssa names, i.e., ssa names that are defined by phi with operands that are not defined or potentially undefined. */ -static hash_set<tree> *possibly_undefined_names = 0; +static hash_set<tree> *possibly_undefined_names; +static hash_map<gphi *, uninit_analysis::func_t::phi_arg_set_t> *defined_args; /* Returns the first bit position (starting from LSB) in mask that is non zero. Returns -1 if the mask is empty. */ @@ -987,10 +988,43 @@ warn_uninitialized_vars (bool wmaybe_uninit) wlimits wlims = { }; wlims.wmaybe_uninit = wmaybe_uninit; - gimple_stmt_iterator gsi; - basic_block bb; + auto_bb_flag ft_reachable (cfun); + + /* Mark blocks that are always executed when we ignore provably + not executed edges. */ + basic_block bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + while (!(bb->flags & ft_reachable)) + { + bb->flags |= ft_reachable; + /* Find a single executable edge. */ + edge_iterator ei; + edge e, ee = NULL; + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->flags & EDGE_EXECUTABLE) + { + if (!ee) + ee = e; + else + { + ee = NULL; + break; + } + } + if (ee) + bb = ee->dest; + else + { + bb = get_immediate_dominator (CDI_POST_DOMINATORS, bb); + if (!bb || bb->index == EXIT_BLOCK) + break; + } + } + FOR_EACH_BB_FN (bb, cfun) { + wlims.always_executed = (bb->flags & ft_reachable); + bb->flags &= ~ft_reachable; + edge_iterator ei; edge e; FOR_EACH_EDGE (e, ei, bb->preds) @@ -1001,14 +1035,10 @@ warn_uninitialized_vars (bool wmaybe_uninit) if (!e) continue; - basic_block succ = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); - /* ??? This could be improved when we use a greedy walk and have - some edges marked as not executable. */ - wlims.always_executed = dominated_by_p (CDI_POST_DOMINATORS, succ, bb); - if (wlims.always_executed) warn_uninit_phi_uses (bb); + gimple_stmt_iterator gsi; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); @@ -1029,7 +1059,7 @@ warn_uninitialized_vars (bool wmaybe_uninit) FOR_EACH_SSA_USE_OPERAND (use_p, stmt, op_iter, SSA_OP_USE) { /* BIT_INSERT_EXPR first operand should not be considered - a use for the purpose of uninit warnings. */ + a use for the purpose of uninit warnings. */ if (gassign *ass = dyn_cast <gassign *> (stmt)) { if (gimple_assign_rhs_code (ass) == BIT_INSERT_EXPR @@ -1040,7 +1070,7 @@ warn_uninitialized_vars (bool wmaybe_uninit) if (wlims.always_executed) warn_uninit (OPT_Wuninitialized, use, SSA_NAME_VAR (use), stmt); - else if (wmaybe_uninit) + else if (wlims.wmaybe_uninit) warn_uninit (OPT_Wmaybe_uninitialized, use, SSA_NAME_VAR (use), stmt); } @@ -1111,7 +1141,7 @@ compute_uninit_opnds_pos (gphi *phi) unsigned n = gimple_phi_num_args (phi); /* Bail out for phi with too many args. */ - if (n > predicate::func_t::max_phi_args) + if (n > uninit_analysis::func_t::max_phi_args) return 0; for (unsigned i = 0; i < n; ++i) @@ -1131,29 +1161,20 @@ compute_uninit_opnds_pos (gphi *phi) MASK_SET_BIT (uninit_opnds, i); } } + /* If we have recorded guarded uses of may-uninit values mask those. */ + if (auto *def_mask = defined_args->get (phi)) + uninit_opnds &= ~*def_mask; return uninit_opnds; } /* Function object type used to determine whether an expression is of interest to the predicate analyzer. */ -struct uninit_undef_val_t: public predicate::func_t +struct uninit_undef_val_t: public uninit_analysis::func_t { - virtual bool operator()(tree) override; virtual unsigned phi_arg_set (gphi *) override; }; -/* Return true if the argument is an expression of interest. */ - -bool -uninit_undef_val_t::operator()(tree val) -{ - if (TREE_CODE (val) == SSA_NAME) - return uninit_undefined_value_p (val); - - return false; -} - /* Return a bitset of PHI arguments of interest. */ unsigned @@ -1162,25 +1183,38 @@ uninit_undef_val_t::phi_arg_set (gphi *phi) return compute_uninit_opnds_pos (phi); } +/* sort helper for find_uninit_use. */ + +static int +cand_cmp (const void *a, const void *b, void *data) +{ + int *bb_to_rpo = (int *)data; + const gimple *sa = *(const gimple * const *)a; + const gimple *sb = *(const gimple * const *)b; + if (bb_to_rpo[gimple_bb (sa)->index] < bb_to_rpo[gimple_bb (sb)->index]) + return -1; + else if (bb_to_rpo[gimple_bb (sa)->index] > bb_to_rpo[gimple_bb (sb)->index]) + return 1; + return 0; +} + /* Searches through all uses of a potentially uninitialized variable defined by PHI and returns a use statement if the use is not properly guarded. It returns NULL if all uses are guarded. UNINIT_OPNDS is a bitvector - holding the position(s) of uninit PHI operands. WORKLIST - is the vector of candidate phis that may be updated by this - function. ADDED_TO_WORKLIST is the pointer set tracking - if the new phi is already in the worklist. */ + holding the position(s) of uninit PHI operands. */ static gimple * -find_uninit_use (gphi *phi, unsigned uninit_opnds, - vec<gphi *> *worklist, hash_set<gphi *> *added_to_worklist) +find_uninit_use (gphi *phi, unsigned uninit_opnds, int *bb_to_rpo) { /* The Boolean predicate guarding the PHI definition. Initialized lazily from PHI in the first call to is_use_guarded() and cached for subsequent iterations. */ uninit_undef_val_t eval; - predicate def_preds (eval); + uninit_analysis def_preds (eval); + /* First process PHIs and record other candidates. */ + auto_vec<gimple *, 64> cands; use_operand_p use_p; imm_use_iterator iter; tree phi_result = gimple_phi_result (phi); @@ -1190,21 +1224,57 @@ find_uninit_use (gphi *phi, unsigned uninit_opnds, if (is_gimple_debug (use_stmt)) continue; - basic_block use_bb; if (gphi *use_phi = dyn_cast<gphi *> (use_stmt)) { - edge e = gimple_phi_arg_edge (use_phi, - PHI_ARG_INDEX_FROM_USE (use_p)); - use_bb = e->src; + unsigned idx = PHI_ARG_INDEX_FROM_USE (use_p); + edge e = gimple_phi_arg_edge (use_phi, idx); /* Do not look for uses in the next iteration of a loop, predicate analysis will not use the appropriate predicates to prove reachability. */ if (e->flags & EDGE_DFS_BACK) continue; + + basic_block use_bb = e->src; + if (def_preds.is_use_guarded (use_stmt, use_bb, phi, uninit_opnds)) + { + /* For a guarded use in a PHI record the PHI argument as + initialized. */ + if (idx < uninit_analysis::func_t::max_phi_args) + { + bool existed_p; + auto &def_mask + = defined_args->get_or_insert (use_phi, &existed_p); + if (!existed_p) + def_mask = 0; + MASK_SET_BIT (def_mask, idx); + } + continue; + } + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Found unguarded use in bb %u: ", + use_bb->index); + print_gimple_stmt (dump_file, use_stmt, 0); + } + /* Found a phi use that is not guarded, mark the phi_result as + possibly undefined. */ + possibly_undefined_names->add (phi_result); } else - use_bb = gimple_bb (use_stmt); + cands.safe_push (use_stmt); + } + /* Sort candidates after RPO. */ + cands.stablesort (cand_cmp, bb_to_rpo); + basic_block use_bb = NULL; + for (gimple *use_stmt : cands) + { + /* We only have to try diagnosing the first use in each block. */ + if (gimple_bb (use_stmt) == use_bb) + continue; + + use_bb = gimple_bb (use_stmt); if (def_preds.is_use_guarded (use_stmt, use_bb, phi, uninit_opnds)) continue; @@ -1214,23 +1284,7 @@ find_uninit_use (gphi *phi, unsigned uninit_opnds, use_bb->index); print_gimple_stmt (dump_file, use_stmt, 0); } - /* Found one real use, return. */ - if (gimple_code (use_stmt) != GIMPLE_PHI) - return use_stmt; - - /* Found a phi use that is not guarded, - add the phi to the worklist. */ - if (!added_to_worklist->add (as_a<gphi *> (use_stmt))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "[WORKLIST]: Update worklist with phi: "); - print_gimple_stmt (dump_file, use_stmt, 0); - } - - worklist->safe_push (as_a<gphi *> (use_stmt)); - possibly_undefined_names->add (phi_result); - } + return use_stmt; } return NULL; @@ -1240,33 +1294,20 @@ find_uninit_use (gphi *phi, unsigned uninit_opnds, and gives warning if there exists a runtime path from the entry to a use of the PHI def that does not contain a definition. In other words, the warning is on the real use. The more dead paths that can be pruned - by the compiler, the fewer false positives the warning is. WORKLIST - is a vector of candidate phis to be examined. ADDED_TO_WORKLIST is - a pointer set tracking if the new phi is added to the worklist or not. */ + by the compiler, the fewer false positives the warning is. */ static void -warn_uninitialized_phi (gphi *phi, vec<gphi *> *worklist, - hash_set<gphi *> *added_to_worklist) +warn_uninitialized_phi (gphi *phi, unsigned uninit_opnds, int *bb_to_rpo) { - /* Don't look at virtual operands. */ - if (virtual_operand_p (gimple_phi_result (phi))) - return; - - unsigned uninit_opnds = compute_uninit_opnds_pos (phi); - if (MASK_EMPTY (uninit_opnds)) - return; - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Examining phi: "); print_gimple_stmt (dump_file, phi, 0); } - gimple *uninit_use_stmt = find_uninit_use (phi, uninit_opnds, - worklist, added_to_worklist); + gimple *uninit_use_stmt = find_uninit_use (phi, uninit_opnds, bb_to_rpo); - /* All uses are properly guarded but a new PHI may have been added - to WORKLIST. */ + /* All uses are properly guarded. */ if (!uninit_use_stmt) return; @@ -1341,10 +1382,6 @@ public: static void execute_late_warn_uninitialized (function *fun) { - basic_block bb; - gphi_iterator gsi; - vec<gphi *> worklist = vNULL; - calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS); @@ -1352,6 +1389,11 @@ execute_late_warn_uninitialized (function *fun) unreachable blocks. */ set_all_edges_as_executable (fun); mark_dfs_back_edges (fun); + int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fun)); + int n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, false); + int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fun)); + for (int i = 0; i < n; ++i) + bb_to_rpo[rpo[i]] = i; /* Re-do the plain uninitialized variable check, as optimization may have straightened control flow. Do this first so that we don't accidentally @@ -1361,11 +1403,15 @@ execute_late_warn_uninitialized (function *fun) timevar_push (TV_TREE_UNINIT); possibly_undefined_names = new hash_set<tree>; - hash_set<gphi *> added_to_worklist; - - /* Initialize worklist */ - FOR_EACH_BB_FN (bb, fun) - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + defined_args = new hash_map<gphi *, uninit_analysis::func_t::phi_arg_set_t>; + + /* Walk the CFG in RPO order so we visit PHIs with defs that are + possibly uninitialized from other PHIs after those. The uninit + predicate analysis will then expand the PHIs predicate with + the predicates of the edges from such PHI defs. */ + for (int i = 0; i < n; ++i) + for (auto gsi = gsi_start_phis (BASIC_BLOCK_FOR_FN (fun, rpo[i])); + !gsi_end_p (gsi); gsi_next (&gsi)) { gphi *phi = gsi.phi (); @@ -1373,35 +1419,19 @@ execute_late_warn_uninitialized (function *fun) if (virtual_operand_p (gimple_phi_result (phi))) continue; - unsigned n = gimple_phi_num_args (phi); - for (unsigned i = 0; i < n; ++i) - { - tree op = gimple_phi_arg_def (phi, i); - if (TREE_CODE (op) == SSA_NAME && uninit_undefined_value_p (op)) - { - worklist.safe_push (phi); - added_to_worklist.add (phi); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "[WORKLIST]: add to initial list " - "for operand %u of: ", i); - print_gimple_stmt (dump_file, phi, 0); - } - break; - } - } - } + unsigned uninit_opnds = compute_uninit_opnds_pos (phi); + if (MASK_EMPTY (uninit_opnds)) + continue; - while (worklist.length () != 0) - { - gphi *cur_phi = 0; - cur_phi = worklist.pop (); - warn_uninitialized_phi (cur_phi, &worklist, &added_to_worklist); - } + warn_uninitialized_phi (phi, uninit_opnds, bb_to_rpo); + } - worklist.release (); + free (rpo); + free (bb_to_rpo); delete possibly_undefined_names; possibly_undefined_names = NULL; + delete defined_args; + defined_args = NULL; free_dominance_info (CDI_POST_DOMINATORS); timevar_pop (TV_TREE_UNINIT); } @@ -1436,10 +1466,7 @@ execute_early_warn_uninitialized (struct function *fun) elimination to compute edge reachability. Don't bother when we only warn for unconditionally executed code though. */ if (!optimize) - { - do_rpo_vn (fun, NULL, NULL, false, false, VN_NOWALK); - free_rpo_vn (); - } + do_rpo_vn (fun, NULL, NULL, false, false, VN_NOWALK); else set_all_edges_as_executable (fun); diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc index 196f19c..219cf5e 100644 --- a/gcc/tree-streamer-in.cc +++ b/gcc/tree-streamer-in.cc @@ -453,6 +453,11 @@ unpack_ts_omp_clause_value_fields (class data_in *data_in, OMP_CLAUSE_DEPEND_KIND (expr) = bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST); break; + case OMP_CLAUSE_DOACROSS: + OMP_CLAUSE_DOACROSS_KIND (expr) + = bp_unpack_enum (bp, omp_clause_doacross_kind, + OMP_CLAUSE_DOACROSS_LAST); + break; case OMP_CLAUSE_MAP: OMP_CLAUSE_SET_MAP_KIND (expr, bp_unpack_enum (bp, gomp_map_kind, GOMP_MAP_LAST)); diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc index d39dc15..9b114dc 100644 --- a/gcc/tree-streamer-out.cc +++ b/gcc/tree-streamer-out.cc @@ -419,6 +419,10 @@ pack_ts_omp_clause_value_fields (struct output_block *ob, bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST, OMP_CLAUSE_DEPEND_KIND (expr)); break; + case OMP_CLAUSE_DOACROSS: + bp_pack_enum (bp, omp_clause_doacross_kind, OMP_CLAUSE_DOACROSS_LAST, + OMP_CLAUSE_DOACROSS_KIND (expr)); + break; case OMP_CLAUSE_MAP: bp_pack_enum (bp, gomp_map_kind, GOMP_MAP_LAST, OMP_CLAUSE_MAP_KIND (expr)); diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc index 86d2264..b68e6cd 100644 --- a/gcc/tree-vect-loop-manip.cc +++ b/gcc/tree-vect-loop-manip.cc @@ -992,7 +992,7 @@ vect_set_loop_condition (class loop *loop, loop_vec_info loop_vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "New loop exit condition: %G", - cond_stmt); + (gimple *) cond_stmt); } /* Helper routine of slpeel_tree_duplicate_loop_to_edge_cfg. @@ -1539,7 +1539,8 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, stmt_vec_info phi_info = loop_vinfo->lookup_stmt (phi); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "vect_update_ivs_after_vectorizer: phi: %G", phi); + "vect_update_ivs_after_vectorizer: phi: %G", + (gimple *) phi); /* Skip reduction and virtual phis. */ if (!iv_phi_p (phi_info)) @@ -1978,7 +1979,8 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters, else ni_minus_gap = niters; - unsigned HOST_WIDE_INT const_vf; + /* To silence some unexpected warnings, simply initialize to 0. */ + unsigned HOST_WIDE_INT const_vf = 0; if (vf.is_constant (&const_vf) && !LOOP_VINFO_USING_PARTIAL_VECTORS_P (loop_vinfo)) { diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 2257b29..24556b5 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -304,7 +304,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) stmt_info = loop_vinfo->lookup_stmt (phi); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "==> examining phi: %G", - phi); + (gimple *) phi); gcc_assert (stmt_info); @@ -489,7 +489,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, class loop *loop, stmt_vec_info stmt_vinfo = loop_vinfo->lookup_stmt (phi); if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", phi); + dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", + (gimple *) phi); /* Skip virtual phi's. The data dependences that are associated with virtual defs/uses (i.e., memory accesses) are analyzed elsewhere. */ @@ -540,7 +541,8 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, class loop *loop, tree def = PHI_RESULT (phi); if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", phi); + dump_printf_loc (MSG_NOTE, vect_location, "Analyze phi: %G", + (gimple *) phi); gcc_assert (!virtual_operand_p (def) && STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_unknown_def_type); @@ -1679,7 +1681,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo) stmt_info = loop_vinfo->lookup_stmt (phi); if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "examining phi: %G", phi); + dump_printf_loc (MSG_NOTE, vect_location, "examining phi: %G", + (gimple *) phi); if (virtual_operand_p (gimple_phi_result (phi))) continue; @@ -2526,7 +2529,7 @@ start_over: if (can_use_lanes && dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "SLP instance %p can use load/store-lanes\n", - instance); + (void *) instance); } else { @@ -4320,7 +4323,8 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "can't unroll as unrolled vectorization factor larger" - " than maximum vectorization factor: %d\n", + " than maximum vectorization factor: " + HOST_WIDE_INT_PRINT_UNSIGNED "\n", LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo)); *suggested_unroll_factor = 1; } @@ -8862,7 +8866,7 @@ vectorizable_induction (loop_vec_info loop_vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "transform induction: created def-use cycle: %G%G", - induction_phi, SSA_NAME_DEF_STMT (vec_def)); + (gimple *) induction_phi, SSA_NAME_DEF_STMT (vec_def)); return true; } @@ -9941,7 +9945,7 @@ vect_transform_loop (loop_vec_info loop_vinfo, gimple *loop_vectorized_call) gphi *phi = si.phi (); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "------>vectorizing phi: %G", phi); + "------>vectorizing phi: %G", (gimple *) phi); stmt_info = loop_vinfo->lookup_stmt (phi); if (!stmt_info) continue; diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 09574bb..d2bd15b 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -742,7 +742,8 @@ vect_split_statement (vec_info *vinfo, stmt_vec_info stmt2_info, tree new_rhs, { dump_printf_loc (MSG_NOTE, vect_location, "into pattern statements: %G", stmt1); - dump_printf_loc (MSG_NOTE, vect_location, "and: %G", new_stmt2); + dump_printf_loc (MSG_NOTE, vect_location, "and: %G", + (gimple *) new_stmt2); } return true; @@ -2267,7 +2268,7 @@ vect_recog_mulhs_pattern (vec_info *vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "created pattern stmt: %G", mulhrs_stmt); + "created pattern stmt: %G", (gimple *) mulhrs_stmt); return vect_convert_output (vinfo, last_stmt_info, lhs_type, mulhrs_stmt, new_vectype); @@ -2473,7 +2474,7 @@ vect_recog_average_pattern (vec_info *vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "created pattern stmt: %G", average_stmt); + "created pattern stmt: %G", (gimple *) average_stmt); return vect_convert_output (vinfo, last_stmt_info, type, average_stmt, new_vectype); @@ -5269,7 +5270,7 @@ vect_determine_precisions_from_range (stmt_vec_info stmt_info, gassign *stmt) dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d" " without loss of precision: %G", sign == SIGNED ? "signed" : "unsigned", - value_precision, stmt); + value_precision, (gimple *) stmt); vect_set_operation_type (stmt_info, type, value_precision, sign); vect_set_min_input_precision (stmt_info, type, value_precision); @@ -5350,7 +5351,7 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt) dump_printf_loc (MSG_NOTE, vect_location, "can narrow to %s:%d" " without affecting users: %G", TYPE_UNSIGNED (type) ? "unsigned" : "signed", - operation_precision, stmt); + operation_precision, (gimple *) stmt); vect_set_operation_type (stmt_info, type, operation_precision, TYPE_SIGN (type)); } diff --git a/gcc/tree-vect-slp-patterns.cc b/gcc/tree-vect-slp-patterns.cc index e6a6db8..dc694b8 100644 --- a/gcc/tree-vect-slp-patterns.cc +++ b/gcc/tree-vect-slp-patterns.cc @@ -96,8 +96,8 @@ vect_pattern_validate_optab (internal_fn ifn, slp_tree node) { if (!vectype) dump_printf_loc (MSG_NOTE, vect_location, - "Target does not support vector type for %T\n", - SLP_TREE_DEF_TYPE (node)); + "Target does not support vector type for %G\n", + STMT_VINFO_STMT (SLP_TREE_REPRESENTATIVE (node))); else dump_printf_loc (MSG_NOTE, vect_location, "Target does not support %s for vector type " diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index dab5dad..b10f69d 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ #include "config.h" +#define INCLUDE_ALGORITHM #include "system.h" #include "coretypes.h" #include "backend.h" @@ -49,7 +50,20 @@ along with GCC; see the file COPYING3. If not see #include "tree-eh.h" #include "tree-cfg.h" #include "alloc-pool.h" - +#include "sreal.h" +#include "predict.h" + +static bool vect_transform_slp_perm_load_1 (vec_info *, slp_tree, + load_permutation_t &, + const vec<tree> &, + gimple_stmt_iterator *, + poly_uint64, bool, bool, + unsigned *, + unsigned * = nullptr, + bool = false); +static int vectorizable_slp_permutation_1 (vec_info *, gimple_stmt_iterator *, + slp_tree, lane_permutation_t &, + vec<slp_tree> &, bool); static bool vectorizable_slp_permutation (vec_info *, gimple_stmt_iterator *, slp_tree, stmt_vector_for_cost *); static void vect_print_slp_tree (dump_flags_t, dump_location_t, slp_tree); @@ -304,6 +318,16 @@ vect_free_oprnd_info (vec<slp_oprnd_info> &oprnds_info) oprnds_info.release (); } +/* Return the execution frequency of NODE (so that a higher value indicates + a "more important" node when optimizing for speed). */ + +static sreal +vect_slp_node_weight (slp_tree node) +{ + stmt_vec_info stmt_info = vect_orig_stmt (SLP_TREE_REPRESENTATIVE (node)); + basic_block bb = gimple_bb (stmt_info->stmt); + return bb->count.to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count); +} /* Return true if STMTS contains a pattern statement. */ @@ -1022,7 +1046,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "Build SLP failed: unsupported call type %G", - call_stmt); + (gimple *) call_stmt); if (is_a <bb_vec_info> (vinfo) && i != 0) continue; /* Fatal mismatch. */ @@ -1529,7 +1553,8 @@ vect_build_slp_tree (vec_info *vinfo, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "re-using %sSLP tree %p\n", - !(*leader)->failed ? "" : "failed ", *leader); + !(*leader)->failed ? "" : "failed ", + (void *) *leader); if (!(*leader)->failed) { SLP_TREE_REF_COUNT (*leader)++; @@ -1566,7 +1591,7 @@ vect_build_slp_tree (vec_info *vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "starting SLP discovery for node %p\n", res); + "starting SLP discovery for node %p\n", (void *) res); poly_uint64 this_max_nunits = 1; slp_tree res_ = vect_build_slp_tree_2 (vinfo, res, stmts, group_size, @@ -1576,7 +1601,7 @@ vect_build_slp_tree (vec_info *vinfo, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "SLP discovery for node %p failed\n", res); + "SLP discovery for node %p failed\n", (void *) res); /* Mark the node invalid so we can detect those when still in use as backedge destinations. */ SLP_TREE_SCALAR_STMTS (res) = vNULL; @@ -1596,7 +1621,8 @@ vect_build_slp_tree (vec_info *vinfo, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "SLP discovery for node %p succeeded\n", res); + "SLP discovery for node %p succeeded\n", + (void *) res); gcc_assert (res_ == res); res->max_nunits = this_max_nunits; vect_update_max_nunits (max_nunits, this_max_nunits); @@ -1816,6 +1842,10 @@ vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node, TREE_TYPE (TREE_TYPE (vec)))); SLP_TREE_VECTYPE (vnode) = TREE_TYPE (vec); } + auto nunits = TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (vnode)); + unsigned HOST_WIDE_INT const_nunits; + if (nunits.is_constant (&const_nunits)) + SLP_TREE_LANES (vnode) = const_nunits; SLP_TREE_VEC_DEFS (vnode).safe_push (vec); /* We are always building a permutation node even if it is an identity permute to shield the rest of the vectorizer from the odd node @@ -2501,12 +2531,14 @@ vect_print_slp_tree (dump_flags_t dump_kind, dump_location_t loc, dump_metadata_t metadata (dump_kind, loc.get_impl_location ()); dump_user_location_t user_loc = loc.get_user_location (); - dump_printf_loc (metadata, user_loc, "node%s %p (max_nunits=%u, refcnt=%u)", + dump_printf_loc (metadata, user_loc, + "node%s %p (max_nunits=" HOST_WIDE_INT_PRINT_UNSIGNED + ", refcnt=%u)", SLP_TREE_DEF_TYPE (node) == vect_external_def ? " (external)" : (SLP_TREE_DEF_TYPE (node) == vect_constant_def ? " (constant)" - : ""), node, + : ""), (void *) node, estimated_poly_value (node->max_nunits), SLP_TREE_REF_COUNT (node)); if (SLP_TREE_VECTYPE (node)) @@ -2869,7 +2901,8 @@ optimize_load_redistribution_1 (scalar_stmts_to_slp_tree_map_t *bst_map, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "converting stmts on permute node %p\n", root); + "converting stmts on permute node %p\n", + (void *) root); bool *matches = XALLOCAVEC (bool, group_size); poly_uint64 max_nunits = 1; @@ -3001,7 +3034,7 @@ vect_match_slp_patterns (slp_instance instance, vec_info *vinfo, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "Analyzing SLP tree %p for patterns\n", - SLP_INSTANCE_TREE (instance)); + (void *) SLP_INSTANCE_TREE (instance)); return vect_match_slp_patterns_2 (ref_node, vinfo, perm_cache, compat_cache, visited); @@ -3193,7 +3226,8 @@ vect_build_slp_instance (vec_info *vinfo, if (dump_enabled_p ()) { dump_printf_loc (MSG_NOTE, vect_location, - "Final SLP tree for instance %p:\n", new_instance); + "Final SLP tree for instance %p:\n", + (void *) new_instance); vect_print_slp_graph (MSG_NOTE, vect_location, SLP_INSTANCE_TREE (new_instance)); } @@ -3531,29 +3565,465 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size) return opt_result::success (); } -struct slpg_vertex +/* Estimates the cost of inserting layout changes into the SLP graph. + It can also say that the insertion is impossible. */ + +struct slpg_layout_cost +{ + slpg_layout_cost () = default; + slpg_layout_cost (sreal, bool); + + static slpg_layout_cost impossible () { return { sreal::max (), 0 }; } + bool is_possible () const { return depth != sreal::max (); } + + bool operator== (const slpg_layout_cost &) const; + bool operator!= (const slpg_layout_cost &) const; + + bool is_better_than (const slpg_layout_cost &, bool) const; + + void add_parallel_cost (const slpg_layout_cost &); + void add_serial_cost (const slpg_layout_cost &); + void split (unsigned int); + + /* The longest sequence of layout changes needed during any traversal + of the partition dag, weighted by execution frequency. + + This is the most important metric when optimizing for speed, since + it helps to ensure that we keep the number of operations on + critical paths to a minimum. */ + sreal depth = 0; + + /* An estimate of the total number of operations needed. It is weighted by + execution frequency when optimizing for speed but not when optimizing for + size. In order to avoid double-counting, a node with a fanout of N will + distribute 1/N of its total cost to each successor. + + This is the most important metric when optimizing for size, since + it helps to keep the total number of operations to a minimum, */ + sreal total = 0; +}; + +/* Construct costs for a node with weight WEIGHT. A higher weight + indicates more frequent execution. IS_FOR_SIZE is true if we are + optimizing for size rather than speed. */ + +slpg_layout_cost::slpg_layout_cost (sreal weight, bool is_for_size) + : depth (weight), total (is_for_size && weight > 0 ? 1 : weight) +{ +} + +bool +slpg_layout_cost::operator== (const slpg_layout_cost &other) const +{ + return depth == other.depth && total == other.total; +} + +bool +slpg_layout_cost::operator!= (const slpg_layout_cost &other) const +{ + return !operator== (other); +} + +/* Return true if these costs are better than OTHER. IS_FOR_SIZE is + true if we are optimizing for size rather than speed. */ + +bool +slpg_layout_cost::is_better_than (const slpg_layout_cost &other, + bool is_for_size) const +{ + if (is_for_size) + { + if (total != other.total) + return total < other.total; + return depth < other.depth; + } + else + { + if (depth != other.depth) + return depth < other.depth; + return total < other.total; + } +} + +/* Increase the costs to account for something with cost INPUT_COST + happening in parallel with the current costs. */ + +void +slpg_layout_cost::add_parallel_cost (const slpg_layout_cost &input_cost) +{ + depth = std::max (depth, input_cost.depth); + total += input_cost.total; +} + +/* Increase the costs to account for something with cost INPUT_COST + happening in series with the current costs. */ + +void +slpg_layout_cost::add_serial_cost (const slpg_layout_cost &other) { - slpg_vertex (slp_tree node_) - : node (node_), perm_in (-1), perm_out (-1) {} + depth += other.depth; + total += other.total; +} + +/* Split the total cost among TIMES successors or predecessors. */ + +void +slpg_layout_cost::split (unsigned int times) +{ + if (times > 1) + total /= times; +} + +/* Information about one node in the SLP graph, for use during + vect_optimize_slp_pass. */ - int get_perm_materialized () const - { return perm_in != perm_out ? perm_in : 0; } +struct slpg_vertex +{ + slpg_vertex (slp_tree node_) : node (node_) {} + /* The node itself. */ slp_tree node; - /* The common permutation on the incoming lanes (towards SLP children). */ - int perm_in; - /* The permutation on the outgoing lanes (towards SLP parents). When - the node is a materialization point for a permute this differs - from perm_in (and is then usually zero). Materialization happens - on the input side. */ - int perm_out; + + /* Which partition the node belongs to, or -1 if none. Nodes outside of + partitions are flexible; they can have whichever layout consumers + want them to have. */ + int partition = -1; + + /* The number of nodes that directly use the result of this one + (i.e. the number of nodes that count this one as a child). */ + unsigned int out_degree = 0; + + /* The execution frequency of the node. */ + sreal weight = 0; + + /* The total execution frequency of all nodes that directly use the + result of this one. */ + sreal out_weight = 0; }; -/* Fill the vertices and leafs vector with all nodes in the SLP graph. */ +/* Information about one partition of the SLP graph, for use during + vect_optimize_slp_pass. */ -static void -vect_slp_build_vertices (hash_set<slp_tree> &visited, slp_tree node, - vec<slpg_vertex> &vertices, vec<int> &leafs) +struct slpg_partition_info +{ + /* The nodes in the partition occupy indices [NODE_BEGIN, NODE_END) + of m_partitioned_nodes. */ + unsigned int node_begin = 0; + unsigned int node_end = 0; + + /* Which layout we've chosen to use for this partition, or -1 if + we haven't picked one yet. */ + int layout = -1; + + /* The number of predecessors and successors in the partition dag. + The predecessors always have lower partition numbers and the + successors always have higher partition numbers. + + Note that the directions of these edges are not necessarily the + same as in the data flow graph. For example, if an SCC has separate + partitions for an inner loop and an outer loop, the inner loop's + partition will have at least two incoming edges from the outer loop's + partition: one for a live-in value and one for a live-out value. + In data flow terms, one of these edges would also be from the outer loop + to the inner loop, but the other would be in the opposite direction. */ + unsigned int in_degree = 0; + unsigned int out_degree = 0; +}; + +/* Information about the costs of using a particular layout for a + particular partition. It can also say that the combination is + impossible. */ + +struct slpg_partition_layout_costs +{ + bool is_possible () const { return internal_cost.is_possible (); } + void mark_impossible () { internal_cost = slpg_layout_cost::impossible (); } + + /* The costs inherited from predecessor partitions. */ + slpg_layout_cost in_cost; + + /* The inherent cost of the layout within the node itself. For example, + this is nonzero for a load if choosing a particular layout would require + the load to permute the loaded elements. It is nonzero for a + VEC_PERM_EXPR if the permutation cannot be eliminated or converted + to full-vector moves. */ + slpg_layout_cost internal_cost; + + /* The costs inherited from successor partitions. */ + slpg_layout_cost out_cost; +}; + +/* This class tries to optimize the layout of vectors in order to avoid + unnecessary shuffling. At the moment, the set of possible layouts are + restricted to bijective permutations. + + The goal of the pass depends on whether we're optimizing for size or + for speed. When optimizing for size, the goal is to reduce the overall + number of layout changes (including layout changes implied by things + like load permutations). When optimizing for speed, the goal is to + reduce the maximum latency attributable to layout changes on any + non-cyclical path through the data flow graph. + + For example, when optimizing a loop nest for speed, we will prefer + to make layout changes outside of a loop rather than inside of a loop, + and will prefer to make layout changes in parallel rather than serially, + even if that increases the overall number of layout changes. + + The high-level procedure is: + + (1) Build a graph in which edges go from uses (parents) to definitions + (children). + + (2) Divide the graph into a dag of strongly-connected components (SCCs). + + (3) When optimizing for speed, partition the nodes in each SCC based + on their containing cfg loop. When optimizing for size, treat + each SCC as a single partition. + + This gives us a dag of partitions. The goal is now to assign a + layout to each partition. + + (4) Construct a set of vector layouts that are worth considering. + Record which nodes must keep their current layout. + + (5) Perform a forward walk over the partition dag (from loads to stores) + accumulating the "forward" cost of using each layout. When visiting + each partition, assign a tentative choice of layout to the partition + and use that choice when calculating the cost of using a different + layout in successor partitions. + + (6) Perform a backward walk over the partition dag (from stores to loads), + accumulating the "backward" cost of using each layout. When visiting + each partition, make a final choice of layout for that partition based + on the accumulated forward costs (from (5)) and backward costs + (from (6)). + + (7) Apply the chosen layouts to the SLP graph. + + For example, consider the SLP statements: + + S1: a_1 = load + loop: + S2: a_2 = PHI<a_1, a_3> + S3: b_1 = load + S4: a_3 = a_2 + b_1 + exit: + S5: a_4 = PHI<a_3> + S6: store a_4 + + S2 and S4 form an SCC and are part of the same loop. Every other + statement is in a singleton SCC. In this example there is a one-to-one + mapping between SCCs and partitions and the partition dag looks like this; + + S1 S3 + \ / + S2+S4 + | + S5 + | + S6 + + S2, S3 and S4 will have a higher execution frequency than the other + statements, so when optimizing for speed, the goal is to avoid any + layout changes: + + - within S3 + - within S2+S4 + - on the S3->S2+S4 edge + + For example, if S3 was originally a reversing load, the goal of the + pass is to make it an unreversed load and change the layout on the + S1->S2+S4 and S2+S4->S5 edges to compensate. (Changing the layout + on S1->S2+S4 and S5->S6 would also be acceptable.) + + The difference between SCCs and partitions becomes important if we + add an outer loop: + + S1: a_1 = ... + loop1: + S2: a_2 = PHI<a_1, a_6> + S3: b_1 = load + S4: a_3 = a_2 + b_1 + loop2: + S5: a_4 = PHI<a_3, a_5> + S6: c_1 = load + S7: a_5 = a_4 + c_1 + exit2: + S8: a_6 = PHI<a_5> + S9: store a_6 + exit1: + + Here, S2, S4, S5, S7 and S8 form a single SCC. However, when optimizing + for speed, we usually do not want restrictions in the outer loop to "infect" + the decision for the inner loop. For example, if an outer-loop node + in the SCC contains a statement with a fixed layout, that should not + prevent the inner loop from using a different layout. Conversely, + the inner loop should not dictate a layout to the outer loop: if the + outer loop does a lot of computation, then it may not be efficient to + do all of that computation in the inner loop's preferred layout. + + So when optimizing for speed, we partition the SCC into S2+S4+S8 (outer) + and S5+S7 (inner). We also try to arrange partitions so that: + + - the partition for an outer loop comes before the partition for + an inner loop + + - if a sibling loop A dominates a sibling loop B, A's partition + comes before B's + + This gives the following partition dag for the example above: + + S1 S3 + \ / + S2+S4+S8 S6 + | \\ / + | S5+S7 + | + S9 + + There are two edges from S2+S4+S8 to S5+S7: one for the edge S4->S5 and + one for a reversal of the edge S7->S8. + + The backward walk picks a layout for S5+S7 before S2+S4+S8. The choice + for S2+S4+S8 therefore has to balance the cost of using the outer loop's + preferred layout against the cost of changing the layout on entry to the + inner loop (S4->S5) and on exit from the inner loop (S7->S8 reversed). + + Although this works well when optimizing for speed, it has the downside + when optimizing for size that the choice of layout for S5+S7 is completely + independent of S9, which lessens the chance of reducing the overall number + of permutations. We therefore do not partition SCCs when optimizing + for size. + + To give a concrete example of the difference between optimizing + for size and speed, consider: + + a[0] = (b[1] << c[3]) - d[1]; + a[1] = (b[0] << c[2]) - d[0]; + a[2] = (b[3] << c[1]) - d[3]; + a[3] = (b[2] << c[0]) - d[2]; + + There are three different layouts here: one for a, one for b and d, + and one for c. When optimizing for speed it is better to permute each + of b, c and d into the order required by a, since those permutations + happen in parallel. But when optimizing for size, it is better to: + + - permute c into the same order as b + - do the arithmetic + - permute the result into the order required by a + + This gives 2 permutations rather than 3. */ + +class vect_optimize_slp_pass +{ +public: + vect_optimize_slp_pass (vec_info *vinfo) : m_vinfo (vinfo) {} + void run (); + +private: + /* Graph building. */ + struct loop *containing_loop (slp_tree); + bool is_cfg_latch_edge (graph_edge *); + void build_vertices (hash_set<slp_tree> &, slp_tree); + void build_vertices (); + void build_graph (); + + /* Partitioning. */ + void create_partitions (); + template<typename T> void for_each_partition_edge (unsigned int, T); + + /* Layout selection. */ + bool is_compatible_layout (slp_tree, unsigned int); + int change_layout_cost (slp_tree, unsigned int, unsigned int); + slpg_partition_layout_costs &partition_layout_costs (unsigned int, + unsigned int); + void change_vec_perm_layout (slp_tree, lane_permutation_t &, + int, unsigned int); + int internal_node_cost (slp_tree, int, unsigned int); + void start_choosing_layouts (); + + /* Cost propagation. */ + slpg_layout_cost edge_layout_cost (graph_edge *, unsigned int, + unsigned int, unsigned int); + slpg_layout_cost total_in_cost (unsigned int); + slpg_layout_cost forward_cost (graph_edge *, unsigned int, unsigned int); + slpg_layout_cost backward_cost (graph_edge *, unsigned int, unsigned int); + void forward_pass (); + void backward_pass (); + + /* Rematerialization. */ + slp_tree get_result_with_layout (slp_tree, unsigned int); + void materialize (); + + /* Clean-up. */ + void remove_redundant_permutations (); + + void dump (); + + vec_info *m_vinfo; + + /* True if we should optimize the graph for size, false if we should + optimize it for speed. (It wouldn't be easy to make this decision + more locally.) */ + bool m_optimize_size; + + /* A graph of all SLP nodes, with edges leading from uses to definitions. + In other words, a node's predecessors are its slp_tree parents and + a node's successors are its slp_tree children. */ + graph *m_slpg = nullptr; + + /* The vertices of M_SLPG, indexed by slp_tree::vertex. */ + auto_vec<slpg_vertex> m_vertices; + + /* The list of all leaves of M_SLPG. such as external definitions, constants, + and loads. */ + auto_vec<int> m_leafs; + + /* This array has one entry for every vector layout that we're considering. + Element 0 is null and indicates "no change". Other entries describe + permutations that are inherent in the current graph and that we would + like to reverse if possible. + + For example, a permutation { 1, 2, 3, 0 } means that something has + effectively been permuted in that way, such as a load group + { a[1], a[2], a[3], a[0] } (viewed as a permutation of a[0:3]). + We'd then like to apply the reverse permutation { 3, 0, 1, 2 } + in order to put things "back" in order. */ + auto_vec<vec<unsigned> > m_perms; + + /* A partitioning of the nodes for which a layout must be chosen. + Each partition represents an <SCC, cfg loop> pair; that is, + nodes in different SCCs belong to different partitions, and nodes + within an SCC can be further partitioned according to a containing + cfg loop. Partition <SCC1, L1> comes before <SCC2, L2> if: + + - SCC1 != SCC2 and SCC1 is a predecessor of SCC2 in a forward walk + from leaves (such as loads) to roots (such as stores). + + - SCC1 == SCC2 and L1's header strictly dominates L2's header. */ + auto_vec<slpg_partition_info> m_partitions; + + /* The list of all nodes for which a layout must be chosen. Nodes for + partition P come before the nodes for partition P+1. Nodes within a + partition are in reverse postorder. */ + auto_vec<unsigned int> m_partitioned_nodes; + + /* Index P * num-layouts + L contains the cost of using layout L + for partition P. */ + auto_vec<slpg_partition_layout_costs> m_partition_layout_costs; + + /* Index N * num-layouts + L, if nonnull, is a node that provides the + original output of node N adjusted to have layout L. */ + auto_vec<slp_tree> m_node_layouts; +}; + +/* Fill the vertices and leafs vector with all nodes in the SLP graph. + Also record whether we should optimize anything for speed rather + than size. */ + +void +vect_optimize_slp_pass::build_vertices (hash_set<slp_tree> &visited, + slp_tree node) { unsigned i; slp_tree child; @@ -3561,8 +4031,15 @@ vect_slp_build_vertices (hash_set<slp_tree> &visited, slp_tree node, if (visited.add (node)) return; - node->vertex = vertices.length (); - vertices.safe_push (slpg_vertex (node)); + if (stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node)) + { + basic_block bb = gimple_bb (vect_orig_stmt (rep)->stmt); + if (optimize_bb_for_speed_p (bb)) + m_optimize_size = false; + } + + node->vertex = m_vertices.length (); + m_vertices.safe_push (slpg_vertex (node)); bool leaf = true; bool force_leaf = false; @@ -3570,7 +4047,7 @@ vect_slp_build_vertices (hash_set<slp_tree> &visited, slp_tree node, if (child) { leaf = false; - vect_slp_build_vertices (visited, child, vertices, leafs); + build_vertices (visited, child); } else force_leaf = true; @@ -3580,21 +4057,19 @@ vect_slp_build_vertices (hash_set<slp_tree> &visited, slp_tree node, and inductions. Force those SLP PHIs to act as leafs to make them backwards reachable. */ if (leaf || force_leaf) - leafs.safe_push (node->vertex); + m_leafs.safe_push (node->vertex); } /* Fill the vertices and leafs vector with all nodes in the SLP graph. */ -static void -vect_slp_build_vertices (vec_info *info, vec<slpg_vertex> &vertices, - vec<int> &leafs) +void +vect_optimize_slp_pass::build_vertices () { hash_set<slp_tree> visited; unsigned i; slp_instance instance; - FOR_EACH_VEC_ELT (info->slp_instances, i, instance) - vect_slp_build_vertices (visited, SLP_INSTANCE_TREE (instance), vertices, - leafs); + FOR_EACH_VEC_ELT (m_vinfo->slp_instances, i, instance) + build_vertices (visited, SLP_INSTANCE_TREE (instance)); } /* Apply (reverse) bijectite PERM to VEC. */ @@ -3625,96 +4100,520 @@ vect_slp_permute (vec<unsigned> perm, } } -/* Return whether permutations PERM_A and PERM_B as recorded in the - PERMS vector are equal. */ +/* Return the cfg loop that contains NODE. */ -static bool -vect_slp_perms_eq (const vec<vec<unsigned> > &perms, - int perm_a, int perm_b) +struct loop * +vect_optimize_slp_pass::containing_loop (slp_tree node) { - return (perm_a == perm_b - || (perm_a != -1 && perm_b != -1 - && perms[perm_a].length () == perms[perm_b].length () - && memcmp (&perms[perm_a][0], &perms[perm_b][0], - sizeof (unsigned) * perms[perm_a].length ()) == 0)); + stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node); + if (!rep) + return ENTRY_BLOCK_PTR_FOR_FN (cfun)->loop_father; + return gimple_bb (vect_orig_stmt (rep)->stmt)->loop_father; } -/* Optimize the SLP graph of VINFO. */ +/* Return true if UD (an edge from a use to a definition) is associated + with a loop latch edge in the cfg. */ -void -vect_optimize_slp (vec_info *vinfo) +bool +vect_optimize_slp_pass::is_cfg_latch_edge (graph_edge *ud) { - if (vinfo->slp_instances.is_empty ()) - return; + slp_tree use = m_vertices[ud->src].node; + slp_tree def = m_vertices[ud->dest].node; + if (SLP_TREE_DEF_TYPE (use) != vect_internal_def + || SLP_TREE_DEF_TYPE (def) != vect_internal_def) + return false; - slp_tree node; - unsigned i; - auto_vec<slpg_vertex> vertices; - auto_vec<int> leafs; - vect_slp_build_vertices (vinfo, vertices, leafs); + stmt_vec_info use_rep = vect_orig_stmt (SLP_TREE_REPRESENTATIVE (use)); + return (is_a<gphi *> (use_rep->stmt) + && bb_loop_header_p (gimple_bb (use_rep->stmt)) + && containing_loop (def) == containing_loop (use)); +} - struct graph *slpg = new_graph (vertices.length ()); - for (slpg_vertex &v : vertices) +/* Build the graph. Mark edges that correspond to cfg loop latch edges with + a nonnull data field. */ + +void +vect_optimize_slp_pass::build_graph () +{ + m_optimize_size = true; + build_vertices (); + + m_slpg = new_graph (m_vertices.length ()); + for (slpg_vertex &v : m_vertices) for (slp_tree child : SLP_TREE_CHILDREN (v.node)) if (child) - add_edge (slpg, v.node->vertex, child->vertex); + { + graph_edge *ud = add_edge (m_slpg, v.node->vertex, child->vertex); + if (is_cfg_latch_edge (ud)) + ud->data = this; + } +} + +/* Return true if E corresponds to a loop latch edge in the cfg. */ + +static bool +skip_cfg_latch_edges (graph_edge *e) +{ + return e->data; +} + +/* Create the node partitions. */ + +void +vect_optimize_slp_pass::create_partitions () +{ + /* Calculate a postorder of the graph, ignoring edges that correspond + to natural latch edges in the cfg. Reading the vector from the end + to the beginning gives the reverse postorder. */ + auto_vec<int> initial_rpo; + graphds_dfs (m_slpg, &m_leafs[0], m_leafs.length (), &initial_rpo, + false, NULL, skip_cfg_latch_edges); + gcc_assert (initial_rpo.length () == m_vertices.length ()); + + /* Calculate the strongly connected components of the graph. */ + auto_vec<int> scc_grouping; + unsigned int num_sccs = graphds_scc (m_slpg, NULL, NULL, &scc_grouping); + + /* Create a new index order in which all nodes from the same SCC are + consecutive. Use scc_pos to record the index of the first node in + each SCC. */ + auto_vec<unsigned int> scc_pos (num_sccs); + int last_component = -1; + unsigned int node_count = 0; + for (unsigned int node_i : scc_grouping) + { + if (last_component != m_slpg->vertices[node_i].component) + { + last_component = m_slpg->vertices[node_i].component; + gcc_assert (last_component == int (scc_pos.length ())); + scc_pos.quick_push (node_count); + } + node_count += 1; + } + gcc_assert (node_count == initial_rpo.length () + && last_component + 1 == int (num_sccs)); + + /* Use m_partitioned_nodes to group nodes into SCC order, with the nodes + inside each SCC following the RPO we calculated above. The fact that + we ignored natural latch edges when calculating the RPO should ensure + that, for natural loop nests: + + - the first node that we encounter in a cfg loop is the loop header phi + - the loop header phis are in dominance order + + Arranging for this is an optimization (see below) rather than a + correctness issue. Unnatural loops with a tangled mess of backedges + will still work correctly, but might give poorer results. + + Also update scc_pos so that it gives 1 + the index of the last node + in the SCC. */ + m_partitioned_nodes.safe_grow (node_count); + for (unsigned int old_i = initial_rpo.length (); old_i-- > 0;) + { + unsigned int node_i = initial_rpo[old_i]; + unsigned int new_i = scc_pos[m_slpg->vertices[node_i].component]++; + m_partitioned_nodes[new_i] = node_i; + } + + /* When optimizing for speed, partition each SCC based on the containing + cfg loop. The order we constructed above should ensure that, for natural + cfg loops, we'll create sub-SCC partitions for outer loops before + the corresponding sub-SCC partitions for inner loops. Similarly, + when one sibling loop A dominates another sibling loop B, we should + create a sub-SCC partition for A before a sub-SCC partition for B. + + As above, nothing depends for correctness on whether this achieves + a natural nesting, but we should get better results when it does. */ + m_partitions.reserve (m_vertices.length ()); + unsigned int next_partition_i = 0; + hash_map<struct loop *, int> loop_partitions; + unsigned int rpo_begin = 0; + unsigned int num_partitioned_nodes = 0; + for (unsigned int rpo_end : scc_pos) + { + loop_partitions.empty (); + unsigned int partition_i = next_partition_i; + for (unsigned int rpo_i = rpo_begin; rpo_i < rpo_end; ++rpo_i) + { + /* Handle externals and constants optimistically throughout. + But treat existing vectors as fixed since we do not handle + permuting them. */ + unsigned int node_i = m_partitioned_nodes[rpo_i]; + auto &vertex = m_vertices[node_i]; + if ((SLP_TREE_DEF_TYPE (vertex.node) == vect_external_def + && !SLP_TREE_VEC_DEFS (vertex.node).exists ()) + || SLP_TREE_DEF_TYPE (vertex.node) == vect_constant_def) + vertex.partition = -1; + else + { + bool existed; + if (m_optimize_size) + existed = next_partition_i > partition_i; + else + { + struct loop *loop = containing_loop (vertex.node); + auto &entry = loop_partitions.get_or_insert (loop, &existed); + if (!existed) + entry = next_partition_i; + partition_i = entry; + } + if (!existed) + { + m_partitions.quick_push (slpg_partition_info ()); + next_partition_i += 1; + } + vertex.partition = partition_i; + num_partitioned_nodes += 1; + m_partitions[partition_i].node_end += 1; + } + } + rpo_begin = rpo_end; + } + + /* Assign ranges of consecutive node indices to each partition, + in partition order. Start with node_end being the same as + node_begin so that the next loop can use it as a counter. */ + unsigned int node_begin = 0; + for (auto &partition : m_partitions) + { + partition.node_begin = node_begin; + node_begin += partition.node_end; + partition.node_end = partition.node_begin; + } + gcc_assert (node_begin == num_partitioned_nodes); + + /* Finally build the list of nodes in partition order. */ + m_partitioned_nodes.truncate (num_partitioned_nodes); + for (unsigned int node_i = 0; node_i < m_vertices.length (); ++node_i) + { + int partition_i = m_vertices[node_i].partition; + if (partition_i >= 0) + { + unsigned int order_i = m_partitions[partition_i].node_end++; + m_partitioned_nodes[order_i] = node_i; + } + } +} - /* Compute (reverse) postorder on the inverted graph. */ - auto_vec<int> ipo; - graphds_dfs (slpg, &leafs[0], leafs.length (), &ipo, false, NULL, NULL); +/* Look for edges from earlier partitions into node NODE_I and edges from + node NODE_I into later partitions. Call: - auto_vec<vec<unsigned> > perms; - perms.safe_push (vNULL); /* zero is no permute */ + FN (ud, other_node_i) - /* Produce initial permutations. */ - for (i = 0; i < leafs.length (); ++i) + for each such use-to-def edge ud, where other_node_i is the node at the + other end of the edge. */ + +template<typename T> +void +vect_optimize_slp_pass::for_each_partition_edge (unsigned int node_i, T fn) +{ + int partition_i = m_vertices[node_i].partition; + for (graph_edge *pred = m_slpg->vertices[node_i].pred; + pred; pred = pred->pred_next) + { + int src_partition_i = m_vertices[pred->src].partition; + if (src_partition_i >= 0 && src_partition_i != partition_i) + fn (pred, pred->src); + } + for (graph_edge *succ = m_slpg->vertices[node_i].succ; + succ; succ = succ->succ_next) { - int idx = leafs[i]; - slp_tree node = vertices[idx].node; + int dest_partition_i = m_vertices[succ->dest].partition; + if (dest_partition_i >= 0 && dest_partition_i != partition_i) + fn (succ, succ->dest); + } +} - /* Handle externals and constants optimistically throughout the - iteration. But treat existing vectors as fixed since we - do not handle permuting them below. */ - if ((SLP_TREE_DEF_TYPE (node) == vect_external_def - && !SLP_TREE_VEC_DEFS (node).exists ()) - || SLP_TREE_DEF_TYPE (node) == vect_constant_def) - continue; +/* Return true if layout LAYOUT_I is compatible with the number of SLP lanes + that NODE would operate on. This test is independent of NODE's actual + operation. */ - /* Leafs do not change across iterations. Note leafs also double - as entries to the reverse graph. */ - if (!slpg->vertices[idx].succ) +bool +vect_optimize_slp_pass::is_compatible_layout (slp_tree node, + unsigned int layout_i) +{ + if (layout_i == 0) + return true; + + if (SLP_TREE_LANES (node) != m_perms[layout_i].length ()) + return false; + + return true; +} + +/* Return the cost (in arbtirary units) of going from layout FROM_LAYOUT_I + to layout TO_LAYOUT_I for a node like NODE. Return -1 if either of the + layouts is incompatible with NODE or if the change is not possible for + some other reason. + + The properties taken from NODE include the number of lanes and the + vector type. The actual operation doesn't matter. */ + +int +vect_optimize_slp_pass::change_layout_cost (slp_tree node, + unsigned int from_layout_i, + unsigned int to_layout_i) +{ + if (!is_compatible_layout (node, from_layout_i) + || !is_compatible_layout (node, to_layout_i)) + return -1; + + if (from_layout_i == to_layout_i) + return 0; + + auto_vec<slp_tree, 1> children (1); + children.quick_push (node); + auto_lane_permutation_t perm (SLP_TREE_LANES (node)); + if (from_layout_i > 0) + for (unsigned int i : m_perms[from_layout_i]) + perm.quick_push ({ 0, i }); + else + for (unsigned int i = 0; i < SLP_TREE_LANES (node); ++i) + perm.quick_push ({ 0, i }); + if (to_layout_i > 0) + vect_slp_permute (m_perms[to_layout_i], perm, true); + auto count = vectorizable_slp_permutation_1 (m_vinfo, nullptr, node, perm, + children, false); + if (count >= 0) + return MAX (count, 1); + + /* ??? In principle we could try changing via layout 0, giving two + layout changes rather than 1. Doing that would require + corresponding support in get_result_with_layout. */ + return -1; +} + +/* Return the costs of assigning layout LAYOUT_I to partition PARTITION_I. */ + +inline slpg_partition_layout_costs & +vect_optimize_slp_pass::partition_layout_costs (unsigned int partition_i, + unsigned int layout_i) +{ + return m_partition_layout_costs[partition_i * m_perms.length () + layout_i]; +} + +/* Change PERM in one of two ways: + + - if IN_LAYOUT_I < 0, accept input operand I in the layout that has been + chosen for child I of NODE. + + - if IN_LAYOUT >= 0, accept all inputs operands with that layout. + + In both cases, arrange for the output to have layout OUT_LAYOUT_I */ + +void +vect_optimize_slp_pass:: +change_vec_perm_layout (slp_tree node, lane_permutation_t &perm, + int in_layout_i, unsigned int out_layout_i) +{ + for (auto &entry : perm) + { + int this_in_layout_i = in_layout_i; + if (this_in_layout_i < 0) { - vertices[idx].perm_in = 0; - vertices[idx].perm_out = 0; + slp_tree in_node = SLP_TREE_CHILDREN (node)[entry.first]; + unsigned int in_partition_i = m_vertices[in_node->vertex].partition; + this_in_layout_i = m_partitions[in_partition_i].layout; } + if (this_in_layout_i > 0) + entry.second = m_perms[this_in_layout_i][entry.second]; + } + if (out_layout_i > 0) + vect_slp_permute (m_perms[out_layout_i], perm, true); +} - /* Loads are the only thing generating permutes. */ - if (!SLP_TREE_LOAD_PERMUTATION (node).exists ()) - continue; +/* Check whether the target allows NODE to be rearranged so that the node's + output has layout OUT_LAYOUT_I. Return the cost of the change if so, + in the same arbitrary units as for change_layout_cost. Return -1 otherwise. + + If NODE is a VEC_PERM_EXPR and IN_LAYOUT_I < 0, also check whether + NODE can adapt to the layout changes that have (perhaps provisionally) + been chosen for NODE's children, so that no extra permutations are + needed on either the input or the output of NODE. + + If NODE is a VEC_PERM_EXPR and IN_LAYOUT_I >= 0, instead assume + that all inputs will be forced into layout IN_LAYOUT_I beforehand. + + IN_LAYOUT_I has no meaning for other types of node. + + Keeping the node as-is is always valid. If the target doesn't appear + to support the node as-is, but might realistically support other layouts, + then layout 0 instead has the cost of a worst-case permutation. On the + one hand, this ensures that every node has at least one valid layout, + avoiding what would otherwise be an awkward special case. On the other, + it still encourages the pass to change an invalid pre-existing layout + choice into a valid one. */ + +int +vect_optimize_slp_pass::internal_node_cost (slp_tree node, int in_layout_i, + unsigned int out_layout_i) +{ + const int fallback_cost = 1; + + if (SLP_TREE_CODE (node) == VEC_PERM_EXPR) + { + auto_lane_permutation_t tmp_perm; + tmp_perm.safe_splice (SLP_TREE_LANE_PERMUTATION (node)); + + /* Check that the child nodes support the chosen layout. Checking + the first child is enough, since any second child would have the + same shape. */ + auto first_child = SLP_TREE_CHILDREN (node)[0]; + if (in_layout_i > 0 + && !is_compatible_layout (first_child, in_layout_i)) + return -1; + + change_vec_perm_layout (node, tmp_perm, in_layout_i, out_layout_i); + int count = vectorizable_slp_permutation_1 (m_vinfo, nullptr, + node, tmp_perm, + SLP_TREE_CHILDREN (node), + false); + if (count < 0) + { + if (in_layout_i == 0 && out_layout_i == 0) + { + /* Use the fallback cost if the node could in principle support + some nonzero layout for both the inputs and the outputs. + Otherwise assume that the node will be rejected later + and rebuilt from scalars. */ + if (SLP_TREE_LANES (node) == SLP_TREE_LANES (first_child)) + return fallback_cost; + return 0; + } + return -1; + } + + /* We currently have no way of telling whether the new layout is cheaper + or more expensive than the old one. But at least in principle, + it should be worth making zero permutations (whole-vector shuffles) + cheaper than real permutations, in case the pass is able to remove + the latter. */ + return count == 0 ? 0 : 1; + } + + stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node); + if (rep + && STMT_VINFO_DATA_REF (rep) + && DR_IS_READ (STMT_VINFO_DATA_REF (rep))) + { + auto_load_permutation_t tmp_perm; + tmp_perm.safe_splice (SLP_TREE_LOAD_PERMUTATION (node)); + if (out_layout_i > 0) + vect_slp_permute (m_perms[out_layout_i], tmp_perm, true); + + poly_uint64 vf = 1; + if (auto loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo)) + vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); + unsigned int n_perms; + if (!vect_transform_slp_perm_load_1 (m_vinfo, node, tmp_perm, vNULL, + nullptr, vf, true, false, &n_perms)) + { + auto rep = SLP_TREE_REPRESENTATIVE (node); + if (out_layout_i == 0) + { + /* Use the fallback cost if the load is an N-to-N permutation. + Otherwise assume that the node will be rejected later + and rebuilt from scalars. */ + if (STMT_VINFO_GROUPED_ACCESS (rep) + && (DR_GROUP_SIZE (DR_GROUP_FIRST_ELEMENT (rep)) + == SLP_TREE_LANES (node))) + return fallback_cost; + return 0; + } + return -1; + } + + /* See the comment above the corresponding VEC_PERM_EXPR handling. */ + return n_perms == 0 ? 0 : 1; + } - /* If splitting out a SLP_TREE_LANE_PERMUTATION can make the - node unpermuted, record this permute. */ + return 0; +} + +/* Decide which element layouts we should consider using. Calculate the + weights associated with inserting layout changes on partition edges. + Also mark partitions that cannot change layout, by setting their + layout to zero. */ + +void +vect_optimize_slp_pass::start_choosing_layouts () +{ + /* Used to assign unique permutation indices. */ + using perm_hash = unbounded_hashmap_traits< + vec_free_hash_base<int_hash_base<unsigned>>, + int_hash<int, -1, -2> + >; + hash_map<vec<unsigned>, int, perm_hash> layout_ids; + + /* Layout 0 is "no change". */ + m_perms.safe_push (vNULL); + + /* Create layouts from existing permutations. */ + auto_load_permutation_t tmp_perm; + for (unsigned int node_i : m_partitioned_nodes) + { + /* Leafs also double as entries to the reverse graph. Allow the + layout of those to be changed. */ + auto &vertex = m_vertices[node_i]; + auto &partition = m_partitions[vertex.partition]; + if (!m_slpg->vertices[node_i].succ) + partition.layout = 0; + + /* Loads and VEC_PERM_EXPRs are the only things generating permutes. */ + slp_tree node = vertex.node; stmt_vec_info dr_stmt = SLP_TREE_REPRESENTATIVE (node); - if (!STMT_VINFO_GROUPED_ACCESS (dr_stmt)) - continue; - dr_stmt = DR_GROUP_FIRST_ELEMENT (dr_stmt); - unsigned imin = DR_GROUP_SIZE (dr_stmt) + 1, imax = 0; + slp_tree child; + unsigned HOST_WIDE_INT imin, imax = 0; bool any_permute = false; + tmp_perm.truncate (0); + if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) + { + /* If splitting out a SLP_TREE_LANE_PERMUTATION can make the node + unpermuted, record a layout that reverses this permutation. */ + gcc_assert (partition.layout == 0); + if (!STMT_VINFO_GROUPED_ACCESS (dr_stmt)) + continue; + dr_stmt = DR_GROUP_FIRST_ELEMENT (dr_stmt); + imin = DR_GROUP_SIZE (dr_stmt) + 1; + tmp_perm.safe_splice (SLP_TREE_LOAD_PERMUTATION (node)); + } + else if (SLP_TREE_CODE (node) == VEC_PERM_EXPR + && SLP_TREE_CHILDREN (node).length () == 1 + && (child = SLP_TREE_CHILDREN (node)[0]) + && (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (child)) + .is_constant (&imin))) + { + /* If the child has the same vector size as this node, + reversing the permutation can make the permutation a no-op. + In other cases it can change a true permutation into a + full-vector extract. */ + tmp_perm.reserve (SLP_TREE_LANES (node)); + for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) + tmp_perm.quick_push (SLP_TREE_LANE_PERMUTATION (node)[j].second); + } + else + continue; + for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) { - unsigned idx = SLP_TREE_LOAD_PERMUTATION (node)[j]; + unsigned idx = tmp_perm[j]; imin = MIN (imin, idx); imax = MAX (imax, idx); - if (idx - SLP_TREE_LOAD_PERMUTATION (node)[0] != j) + if (idx - tmp_perm[0] != j) any_permute = true; } - /* If there's no permute no need to split one out. */ - if (!any_permute) - continue; /* If the span doesn't match we'd disrupt VF computation, avoid that for now. */ if (imax - imin + 1 != SLP_TREE_LANES (node)) continue; + /* If there's no permute no need to split one out. In this case + we can consider turning a load into a permuted load, if that + turns out to be cheaper than alternatives. */ + if (!any_permute) + { + partition.layout = -1; + continue; + } /* For now only handle true permutes, like vect_attempt_slp_rearrange_stmts did. This allows us to be lazy @@ -3723,7 +4622,7 @@ vect_optimize_slp (vec_info *vinfo) auto_sbitmap load_index (SLP_TREE_LANES (node)); bitmap_clear (load_index); for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) - bitmap_set_bit (load_index, SLP_TREE_LOAD_PERMUTATION (node)[j] - imin); + bitmap_set_bit (load_index, tmp_perm[j] - imin); unsigned j; for (j = 0; j < SLP_TREE_LANES (node); ++j) if (!bitmap_bit_p (load_index, j)) @@ -3734,408 +4633,744 @@ vect_optimize_slp (vec_info *vinfo) vec<unsigned> perm = vNULL; perm.safe_grow (SLP_TREE_LANES (node), true); for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) - perm[j] = SLP_TREE_LOAD_PERMUTATION (node)[j] - imin; - perms.safe_push (perm); - vertices[idx].perm_in = perms.length () - 1; - vertices[idx].perm_out = perms.length () - 1; + perm[j] = tmp_perm[j] - imin; + + if (int (m_perms.length ()) >= param_vect_max_layout_candidates) + { + /* Continue to use existing layouts, but don't add any more. */ + int *entry = layout_ids.get (perm); + partition.layout = entry ? *entry : 0; + perm.release (); + } + else + { + bool existed; + int &layout_i = layout_ids.get_or_insert (perm, &existed); + if (existed) + perm.release (); + else + { + layout_i = m_perms.length (); + m_perms.safe_push (perm); + } + partition.layout = layout_i; + } } - /* In addition to the above we have to mark outgoing permutes facing - non-reduction graph entries that are not represented as to be - materialized. */ - for (slp_instance instance : vinfo->slp_instances) + /* Initially assume that every layout is possible and has zero cost + in every partition. */ + m_partition_layout_costs.safe_grow_cleared (m_partitions.length () + * m_perms.length ()); + + /* We have to mark outgoing permutations facing non-reduction graph + entries that are not represented as to be materialized. */ + for (slp_instance instance : m_vinfo->slp_instances) if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_ctor) { - /* Just setting perm_out isn't enough for the propagation to - pick this up. */ - vertices[SLP_INSTANCE_TREE (instance)->vertex].perm_in = 0; - vertices[SLP_INSTANCE_TREE (instance)->vertex].perm_out = 0; + unsigned int node_i = SLP_INSTANCE_TREE (instance)->vertex; + m_partitions[m_vertices[node_i].partition].layout = 0; } - /* Propagate permutes along the graph and compute materialization points. */ - bool changed; - bool do_materialization = false; - unsigned iteration = 0; - do + /* Check which layouts each node and partition can handle. Calculate the + weights associated with inserting layout changes on edges. */ + for (unsigned int node_i : m_partitioned_nodes) { - changed = false; - ++iteration; + auto &vertex = m_vertices[node_i]; + auto &partition = m_partitions[vertex.partition]; + slp_tree node = vertex.node; - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "SLP optimize iteration %d\n", iteration); + if (stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node)) + { + vertex.weight = vect_slp_node_weight (node); + + /* We do not handle stores with a permutation, so all + incoming permutations must have been materialized. */ + if (STMT_VINFO_DATA_REF (rep) + && DR_IS_WRITE (STMT_VINFO_DATA_REF (rep))) + /* ??? We're forcing materialization in place + of the child here, we'd need special handling + in materialization to leave layout -1 here. */ + partition.layout = 0; + + /* We cannot change the layout of an operation that is + not independent on lanes. Note this is an explicit + negative list since that's much shorter than the respective + positive one but it's critical to keep maintaining it. */ + if (is_gimple_call (STMT_VINFO_STMT (rep))) + switch (gimple_call_combined_fn (STMT_VINFO_STMT (rep))) + { + case CFN_COMPLEX_ADD_ROT90: + case CFN_COMPLEX_ADD_ROT270: + case CFN_COMPLEX_MUL: + case CFN_COMPLEX_MUL_CONJ: + case CFN_VEC_ADDSUB: + case CFN_VEC_FMADDSUB: + case CFN_VEC_FMSUBADD: + partition.layout = 0; + default:; + } + } + + auto process_edge = [&](graph_edge *ud, unsigned int other_node_i) + { + auto &other_vertex = m_vertices[other_node_i]; + + /* Count the number of edges from earlier partitions and the number + of edges to later partitions. */ + if (other_vertex.partition < vertex.partition) + partition.in_degree += 1; + else + partition.out_degree += 1; + + /* If the current node uses the result of OTHER_NODE_I, accumulate + the effects of that. */ + if (ud->src == int (node_i)) + { + other_vertex.out_weight += vertex.weight; + other_vertex.out_degree += 1; + } + }; + for_each_partition_edge (node_i, process_edge); + } +} - for (i = vertices.length (); i > 0 ; --i) +/* Return the incoming costs for node NODE_I, assuming that each input keeps + its current (provisional) choice of layout. The inputs do not necessarily + have the same layout as each other. */ + +slpg_layout_cost +vect_optimize_slp_pass::total_in_cost (unsigned int node_i) +{ + auto &vertex = m_vertices[node_i]; + slpg_layout_cost cost; + auto add_cost = [&](graph_edge *, unsigned int other_node_i) + { + auto &other_vertex = m_vertices[other_node_i]; + if (other_vertex.partition < vertex.partition) { - int idx = ipo[i-1]; - slp_tree node = vertices[idx].node; + auto &other_partition = m_partitions[other_vertex.partition]; + auto &other_costs = partition_layout_costs (other_vertex.partition, + other_partition.layout); + slpg_layout_cost this_cost = other_costs.in_cost; + this_cost.add_serial_cost (other_costs.internal_cost); + this_cost.split (other_partition.out_degree); + cost.add_parallel_cost (this_cost); + } + }; + for_each_partition_edge (node_i, add_cost); + return cost; +} + +/* Return the cost of switching between layout LAYOUT1_I (at node NODE1_I) + and layout LAYOUT2_I on cross-partition use-to-def edge UD. Return + slpg_layout_cost::impossible () if the change isn't possible. */ - /* Handle externals and constants optimistically throughout the - iteration. */ - if (SLP_TREE_DEF_TYPE (node) == vect_external_def - || SLP_TREE_DEF_TYPE (node) == vect_constant_def) +slpg_layout_cost +vect_optimize_slp_pass:: +edge_layout_cost (graph_edge *ud, unsigned int node1_i, unsigned int layout1_i, + unsigned int layout2_i) +{ + auto &def_vertex = m_vertices[ud->dest]; + auto &use_vertex = m_vertices[ud->src]; + auto def_layout_i = ud->dest == int (node1_i) ? layout1_i : layout2_i; + auto use_layout_i = ud->dest == int (node1_i) ? layout2_i : layout1_i; + auto factor = change_layout_cost (def_vertex.node, def_layout_i, + use_layout_i); + if (factor < 0) + return slpg_layout_cost::impossible (); + + /* We have a choice of putting the layout change at the site of the + definition or at the site of the use. Prefer the former when + optimizing for size or when the execution frequency of the + definition is no greater than the combined execution frequencies of + the uses. When putting the layout change at the site of the definition, + divvy up the cost among all consumers. */ + if (m_optimize_size || def_vertex.weight <= def_vertex.out_weight) + { + slpg_layout_cost cost = { def_vertex.weight * factor, m_optimize_size }; + cost.split (def_vertex.out_degree); + return cost; + } + return { use_vertex.weight * factor, m_optimize_size }; +} + +/* UD represents a use-def link between FROM_NODE_I and a node in a later + partition; FROM_NODE_I could be the definition node or the use node. + The node at the other end of the link wants to use layout TO_LAYOUT_I. + Return the cost of any necessary fix-ups on edge UD, or return + slpg_layout_cost::impossible () if the change isn't possible. + + At this point, FROM_NODE_I's partition has chosen the cheapest + layout based on the information available so far, but this choice + is only provisional. */ + +slpg_layout_cost +vect_optimize_slp_pass::forward_cost (graph_edge *ud, unsigned int from_node_i, + unsigned int to_layout_i) +{ + auto &from_vertex = m_vertices[from_node_i]; + unsigned int from_partition_i = from_vertex.partition; + slpg_partition_info &from_partition = m_partitions[from_partition_i]; + gcc_assert (from_partition.layout >= 0); + + /* First calculate the cost on the assumption that FROM_PARTITION sticks + with its current layout preference. */ + slpg_layout_cost cost = slpg_layout_cost::impossible (); + auto edge_cost = edge_layout_cost (ud, from_node_i, + from_partition.layout, to_layout_i); + if (edge_cost.is_possible ()) + { + auto &from_costs = partition_layout_costs (from_partition_i, + from_partition.layout); + cost = from_costs.in_cost; + cost.add_serial_cost (from_costs.internal_cost); + cost.split (from_partition.out_degree); + cost.add_serial_cost (edge_cost); + } + + /* Take the minimum of that cost and the cost that applies if + FROM_PARTITION instead switches to TO_LAYOUT_I. */ + auto &direct_layout_costs = partition_layout_costs (from_partition_i, + to_layout_i); + if (direct_layout_costs.is_possible ()) + { + slpg_layout_cost direct_cost = direct_layout_costs.in_cost; + direct_cost.add_serial_cost (direct_layout_costs.internal_cost); + direct_cost.split (from_partition.out_degree); + if (!cost.is_possible () + || direct_cost.is_better_than (cost, m_optimize_size)) + cost = direct_cost; + } + + return cost; +} + +/* UD represents a use-def link between TO_NODE_I and a node in an earlier + partition; TO_NODE_I could be the definition node or the use node. + The node at the other end of the link wants to use layout FROM_LAYOUT_I; + return the cost of any necessary fix-ups on edge UD, or + slpg_layout_cost::impossible () if the choice cannot be made. + + At this point, TO_NODE_I's partition has a fixed choice of layout. */ + +slpg_layout_cost +vect_optimize_slp_pass::backward_cost (graph_edge *ud, unsigned int to_node_i, + unsigned int from_layout_i) +{ + auto &to_vertex = m_vertices[to_node_i]; + unsigned int to_partition_i = to_vertex.partition; + slpg_partition_info &to_partition = m_partitions[to_partition_i]; + gcc_assert (to_partition.layout >= 0); + + /* If TO_NODE_I is a VEC_PERM_EXPR consumer, see whether it can be + adjusted for this input having layout FROM_LAYOUT_I. Assume that + any other inputs keep their current choice of layout. */ + auto &to_costs = partition_layout_costs (to_partition_i, + to_partition.layout); + if (ud->src == int (to_node_i) + && SLP_TREE_CODE (to_vertex.node) == VEC_PERM_EXPR) + { + auto &from_partition = m_partitions[m_vertices[ud->dest].partition]; + auto old_layout = from_partition.layout; + from_partition.layout = from_layout_i; + int factor = internal_node_cost (to_vertex.node, -1, + to_partition.layout); + from_partition.layout = old_layout; + if (factor >= 0) + { + slpg_layout_cost cost = to_costs.out_cost; + cost.add_serial_cost ({ to_vertex.weight * factor, + m_optimize_size }); + cost.split (to_partition.in_degree); + return cost; + } + } + + /* Compute the cost if we insert any necessary layout change on edge UD. */ + auto edge_cost = edge_layout_cost (ud, to_node_i, + to_partition.layout, from_layout_i); + if (edge_cost.is_possible ()) + { + slpg_layout_cost cost = to_costs.out_cost; + cost.add_serial_cost (to_costs.internal_cost); + cost.split (to_partition.in_degree); + cost.add_serial_cost (edge_cost); + return cost; + } + + return slpg_layout_cost::impossible (); +} + +/* Make a forward pass through the partitions, accumulating input costs. + Make a tentative (provisional) choice of layout for each partition, + ensuring that this choice still allows later partitions to keep + their original layout. */ + +void +vect_optimize_slp_pass::forward_pass () +{ + for (unsigned int partition_i = 0; partition_i < m_partitions.length (); + ++partition_i) + { + auto &partition = m_partitions[partition_i]; + + /* If the partition consists of a single VEC_PERM_EXPR, precompute + the incoming cost that would apply if every predecessor partition + keeps its current layout. This is used within the loop below. */ + slpg_layout_cost in_cost; + slp_tree single_node = nullptr; + if (partition.node_end == partition.node_begin + 1) + { + unsigned int node_i = m_partitioned_nodes[partition.node_begin]; + single_node = m_vertices[node_i].node; + if (SLP_TREE_CODE (single_node) == VEC_PERM_EXPR) + in_cost = total_in_cost (node_i); + } + + /* Go through the possible layouts. Decide which ones are valid + for this partition and record which of the valid layouts has + the lowest cost. */ + unsigned int min_layout_i = 0; + slpg_layout_cost min_layout_cost = slpg_layout_cost::impossible (); + for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i) + { + auto &layout_costs = partition_layout_costs (partition_i, layout_i); + if (!layout_costs.is_possible ()) continue; - /* We still eventually have failed backedge SLP nodes in the - graph, those are only cancelled when analyzing operations. - Simply treat them as transparent ops, propagating permutes - through them. */ - if (SLP_TREE_DEF_TYPE (node) == vect_internal_def) + /* If the recorded layout is already 0 then the layout cannot + change. */ + if (partition.layout == 0 && layout_i != 0) { - /* We do not handle stores with a permutation, so all - incoming permutes must have been materialized. */ - stmt_vec_info rep = SLP_TREE_REPRESENTATIVE (node); - if (STMT_VINFO_DATA_REF (rep) - && DR_IS_WRITE (STMT_VINFO_DATA_REF (rep))) - { - /* ??? We're forcing materialization in place - of the child here, we'd need special handling - in materialization to leave perm_in -1 here. */ - vertices[idx].perm_in = 0; - vertices[idx].perm_out = 0; - } - /* We cannot move a permute across an operation that is - not independent on lanes. Note this is an explicit - negative list since that's much shorter than the respective - positive one but it's critical to keep maintaining it. */ - if (is_gimple_call (STMT_VINFO_STMT (rep))) - switch (gimple_call_combined_fn (STMT_VINFO_STMT (rep))) - { - case CFN_COMPLEX_ADD_ROT90: - case CFN_COMPLEX_ADD_ROT270: - case CFN_COMPLEX_MUL: - case CFN_COMPLEX_MUL_CONJ: - case CFN_VEC_ADDSUB: - case CFN_VEC_FMADDSUB: - case CFN_VEC_FMSUBADD: - vertices[idx].perm_in = 0; - vertices[idx].perm_out = 0; - default:; - } + layout_costs.mark_impossible (); + continue; } - if (!slpg->vertices[idx].succ) - /* Pick up pre-computed leaf values. */ - ; - else + bool is_possible = true; + for (unsigned int order_i = partition.node_begin; + order_i < partition.node_end; ++order_i) { - bool any_succ_perm_out_m1 = false; - int perm_in = vertices[idx].perm_in; - for (graph_edge *succ = slpg->vertices[idx].succ; - succ; succ = succ->succ_next) + unsigned int node_i = m_partitioned_nodes[order_i]; + auto &vertex = m_vertices[node_i]; + + /* Reject the layout if it is individually incompatible + with any node in the partition. */ + if (!is_compatible_layout (vertex.node, layout_i)) { - int succ_idx = succ->dest; - int succ_perm = vertices[succ_idx].perm_out; - /* Handle unvisited (and constant) nodes optimistically. */ - /* ??? But for constants once we want to handle - non-bijective permutes we have to verify the permute, - when unifying lanes, will not unify different constants. - For example see gcc.dg/vect/bb-slp-14.c for a case - that would break. */ - if (succ_perm == -1) - { - /* When we handled a non-leaf optimistically, note - that so we can adjust its outgoing permute below. */ - slp_tree succ_node = vertices[succ_idx].node; - if (SLP_TREE_DEF_TYPE (succ_node) != vect_external_def - && SLP_TREE_DEF_TYPE (succ_node) != vect_constant_def) - any_succ_perm_out_m1 = true; - continue; - } - if (perm_in == -1) - perm_in = succ_perm; - else if (succ_perm == 0 - || !vect_slp_perms_eq (perms, perm_in, succ_perm)) - { - perm_in = 0; - break; - } + is_possible = false; + break; } - /* Adjust any incoming permutes we treated optimistically. */ - if (perm_in != -1 && any_succ_perm_out_m1) + auto add_cost = [&](graph_edge *ud, unsigned int other_node_i) { - for (graph_edge *succ = slpg->vertices[idx].succ; - succ; succ = succ->succ_next) + auto &other_vertex = m_vertices[other_node_i]; + if (other_vertex.partition < vertex.partition) { - slp_tree succ_node = vertices[succ->dest].node; - if (vertices[succ->dest].perm_out == -1 - && SLP_TREE_DEF_TYPE (succ_node) != vect_external_def - && SLP_TREE_DEF_TYPE (succ_node) != vect_constant_def) - { - vertices[succ->dest].perm_out = perm_in; - /* And ensure this propagates. */ - if (vertices[succ->dest].perm_in == -1) - vertices[succ->dest].perm_in = perm_in; - } + /* Accumulate the incoming costs from earlier + partitions, plus the cost of any layout changes + on UD itself. */ + auto cost = forward_cost (ud, other_node_i, layout_i); + if (!cost.is_possible ()) + is_possible = false; + else + layout_costs.in_cost.add_parallel_cost (cost); } - changed = true; + else + /* Reject the layout if it would make layout 0 impossible + for later partitions. This amounts to testing that the + target supports reversing the layout change on edges + to later partitions. + + In principle, it might be possible to push a layout + change all the way down a graph, so that it never + needs to be reversed and so that the target doesn't + need to support the reverse operation. But it would + be awkward to bail out if we hit a partition that + does not support the new layout, especially since + we are not dealing with a lattice. */ + is_possible &= edge_layout_cost (ud, other_node_i, 0, + layout_i).is_possible (); + }; + for_each_partition_edge (node_i, add_cost); + + /* Accumulate the cost of using LAYOUT_I within NODE, + both for the inputs and the outputs. */ + int factor = internal_node_cost (vertex.node, layout_i, + layout_i); + if (factor < 0) + { + is_possible = false; + break; } + else if (factor) + layout_costs.internal_cost.add_serial_cost + ({ vertex.weight * factor, m_optimize_size }); + } + if (!is_possible) + { + layout_costs.mark_impossible (); + continue; + } + + /* Combine the incoming and partition-internal costs. */ + slpg_layout_cost combined_cost = layout_costs.in_cost; + combined_cost.add_serial_cost (layout_costs.internal_cost); - if (!vect_slp_perms_eq (perms, perm_in, - vertices[idx].perm_in)) + /* If this partition consists of a single VEC_PERM_EXPR, see + if the VEC_PERM_EXPR can be changed to support output layout + LAYOUT_I while keeping all the provisional choices of input + layout. */ + if (single_node + && SLP_TREE_CODE (single_node) == VEC_PERM_EXPR) + { + int factor = internal_node_cost (single_node, -1, layout_i); + if (factor >= 0) { - /* Make sure we eventually converge. */ - gcc_checking_assert (vertices[idx].perm_in == -1 - || perm_in == 0); - vertices[idx].perm_in = perm_in; - - /* While we can handle VEC_PERM nodes as transparent - pass-through they can be a cheap materialization - point as well. In addition they can act as source - of a random permutation as well. - The following ensures that former materialization - points that now have zero incoming permutes no - longer appear as such and that former "any" permutes - get pass-through. We keep VEC_PERM nodes optimistic - as "any" outgoing permute though. */ - if (vertices[idx].perm_out != 0 - && SLP_TREE_CODE (node) != VEC_PERM_EXPR) - vertices[idx].perm_out = perm_in; - changed = true; + auto weight = m_vertices[single_node->vertex].weight; + slpg_layout_cost internal_cost + = { weight * factor, m_optimize_size }; + + slpg_layout_cost alt_cost = in_cost; + alt_cost.add_serial_cost (internal_cost); + if (alt_cost.is_better_than (combined_cost, m_optimize_size)) + { + combined_cost = alt_cost; + layout_costs.in_cost = in_cost; + layout_costs.internal_cost = internal_cost; + } } } - /* Elide pruning at materialization points in the first - iteration phase. */ - if (!do_materialization) - continue; + /* Record the layout with the lowest cost. Prefer layout 0 in + the event of a tie between it and another layout. */ + if (!min_layout_cost.is_possible () + || combined_cost.is_better_than (min_layout_cost, + m_optimize_size)) + { + min_layout_i = layout_i; + min_layout_cost = combined_cost; + } + } + + /* This loop's handling of earlier partitions should ensure that + choosing the original layout for the current partition is no + less valid than it was in the original graph, even with the + provisional layout choices for those earlier partitions. */ + gcc_assert (min_layout_cost.is_possible ()); + partition.layout = min_layout_i; + } +} + +/* Make a backward pass through the partitions, accumulating output costs. + Make a final choice of layout for each partition. */ + +void +vect_optimize_slp_pass::backward_pass () +{ + for (unsigned int partition_i = m_partitions.length (); partition_i-- > 0;) + { + auto &partition = m_partitions[partition_i]; - int perm = vertices[idx].perm_out; - if (perm == 0 || perm == -1) + unsigned int min_layout_i = 0; + slpg_layout_cost min_layout_cost = slpg_layout_cost::impossible (); + for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i) + { + auto &layout_costs = partition_layout_costs (partition_i, layout_i); + if (!layout_costs.is_possible ()) continue; - /* Decide on permute materialization. Look whether there's - a use (pred) edge that is permuted differently than us. - In that case mark ourselves so the permutation is applied. */ - bool all_preds_permuted = slpg->vertices[idx].pred != NULL; - if (all_preds_permuted) - for (graph_edge *pred = slpg->vertices[idx].pred; - pred; pred = pred->pred_next) - { - int pred_perm = vertices[pred->src].perm_in; - gcc_checking_assert (pred_perm != -1); - if (!vect_slp_perms_eq (perms, perm, pred_perm)) - { - all_preds_permuted = false; - break; - } - } - if (!all_preds_permuted) + /* Accumulate the costs from successor partitions. */ + bool is_possible = true; + for (unsigned int order_i = partition.node_begin; + order_i < partition.node_end; ++order_i) + { + unsigned int node_i = m_partitioned_nodes[order_i]; + auto &vertex = m_vertices[node_i]; + auto add_cost = [&](graph_edge *ud, unsigned int other_node_i) + { + auto &other_vertex = m_vertices[other_node_i]; + auto &other_partition = m_partitions[other_vertex.partition]; + if (other_vertex.partition > vertex.partition) + { + /* Accumulate the incoming costs from later + partitions, plus the cost of any layout changes + on UD itself. */ + auto cost = backward_cost (ud, other_node_i, layout_i); + if (!cost.is_possible ()) + is_possible = false; + else + layout_costs.out_cost.add_parallel_cost (cost); + } + else + /* Make sure that earlier partitions can (if necessary + or beneficial) keep the layout that they chose in + the forward pass. This ensures that there is at + least one valid choice of layout. */ + is_possible &= edge_layout_cost (ud, other_node_i, + other_partition.layout, + layout_i).is_possible (); + }; + for_each_partition_edge (node_i, add_cost); + } + if (!is_possible) { - vertices[idx].perm_out = 0; - changed = true; + layout_costs.mark_impossible (); + continue; + } + + /* Locally combine the costs from the forward and backward passes. + (This combined cost is not passed on, since that would lead + to double counting.) */ + slpg_layout_cost combined_cost = layout_costs.in_cost; + combined_cost.add_serial_cost (layout_costs.internal_cost); + combined_cost.add_serial_cost (layout_costs.out_cost); + + /* Record the layout with the lowest cost. Prefer layout 0 in + the event of a tie between it and another layout. */ + if (!min_layout_cost.is_possible () + || combined_cost.is_better_than (min_layout_cost, + m_optimize_size)) + { + min_layout_i = layout_i; + min_layout_cost = combined_cost; } } - /* If the initial propagation converged, switch on materialization - and re-propagate. */ - if (!changed && !do_materialization) + gcc_assert (min_layout_cost.is_possible ()); + partition.layout = min_layout_i; + } +} + +/* Return a node that applies layout TO_LAYOUT_I to the original form of NODE. + NODE already has the layout that was selected for its partition. */ + +slp_tree +vect_optimize_slp_pass::get_result_with_layout (slp_tree node, + unsigned int to_layout_i) +{ + unsigned int result_i = node->vertex * m_perms.length () + to_layout_i; + slp_tree result = m_node_layouts[result_i]; + if (result) + return result; + + if (SLP_TREE_DEF_TYPE (node) == vect_constant_def + || SLP_TREE_DEF_TYPE (node) == vect_external_def) + { + /* If the vector is uniform or unchanged, there's nothing to do. */ + if (to_layout_i == 0 || vect_slp_tree_uniform_p (node)) + result = node; + else { - do_materialization = true; - changed = true; + auto scalar_ops = SLP_TREE_SCALAR_OPS (node).copy (); + result = vect_create_new_slp_node (scalar_ops); + vect_slp_permute (m_perms[to_layout_i], scalar_ops, true); } } - while (changed); - statistics_histogram_event (cfun, "SLP optimize perm iterations", iteration); - - /* Materialize. */ - for (i = 0; i < vertices.length (); ++i) + else { - int perm_in = vertices[i].perm_in; - slp_tree node = vertices[i].node; + unsigned int partition_i = m_vertices[node->vertex].partition; + unsigned int from_layout_i = m_partitions[partition_i].layout; + if (from_layout_i == to_layout_i) + return node; - /* First permute invariant/external original successors, we handle - those optimistically during propagation and duplicate them if - they are used with different permutations. */ - unsigned j; - slp_tree child; - if (perm_in > 0) - FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), j, child) - { - if (!child - || (SLP_TREE_DEF_TYPE (child) != vect_constant_def - && SLP_TREE_DEF_TYPE (child) != vect_external_def)) - continue; + /* If NODE is itself a VEC_PERM_EXPR, try to create a parallel + permutation instead of a serial one. Leave the new permutation + in TMP_PERM on success. */ + auto_lane_permutation_t tmp_perm; + unsigned int num_inputs = 1; + if (SLP_TREE_CODE (node) == VEC_PERM_EXPR) + { + tmp_perm.safe_splice (SLP_TREE_LANE_PERMUTATION (node)); + if (from_layout_i != 0) + vect_slp_permute (m_perms[from_layout_i], tmp_perm, false); + if (to_layout_i != 0) + vect_slp_permute (m_perms[to_layout_i], tmp_perm, true); + if (vectorizable_slp_permutation_1 (m_vinfo, nullptr, node, + tmp_perm, + SLP_TREE_CHILDREN (node), + false) >= 0) + num_inputs = SLP_TREE_CHILDREN (node).length (); + else + tmp_perm.truncate (0); + } - /* If the vector is uniform there's nothing to do. */ - if (vect_slp_tree_uniform_p (child)) - continue; + if (dump_enabled_p ()) + { + if (tmp_perm.length () > 0) + dump_printf_loc (MSG_NOTE, vect_location, + "duplicating permutation node %p with" + " layout %d\n", + (void *) node, to_layout_i); + else + dump_printf_loc (MSG_NOTE, vect_location, + "inserting permutation node in place of %p\n", + (void *) node); + } - /* We can end up sharing some externals via two_operator - handling. Be prepared to unshare those. */ - if (child->refcnt != 1) - { - gcc_assert (slpg->vertices[child->vertex].pred->pred_next); - SLP_TREE_CHILDREN (node)[j] = child - = vect_create_new_slp_node - (SLP_TREE_SCALAR_OPS (child).copy ()); - } - vect_slp_permute (perms[perm_in], - SLP_TREE_SCALAR_OPS (child), true); - } + unsigned int num_lanes = SLP_TREE_LANES (node); + result = vect_create_new_slp_node (num_inputs, VEC_PERM_EXPR); + if (SLP_TREE_SCALAR_STMTS (node).length ()) + { + auto &stmts = SLP_TREE_SCALAR_STMTS (result); + stmts.safe_splice (SLP_TREE_SCALAR_STMTS (result)); + if (from_layout_i != 0) + vect_slp_permute (m_perms[from_layout_i], stmts, false); + if (to_layout_i != 0) + vect_slp_permute (m_perms[to_layout_i], stmts, true); + } + SLP_TREE_REPRESENTATIVE (result) = SLP_TREE_REPRESENTATIVE (node); + SLP_TREE_LANES (result) = num_lanes; + SLP_TREE_VECTYPE (result) = SLP_TREE_VECTYPE (node); + result->vertex = -1; + + auto &lane_perm = SLP_TREE_LANE_PERMUTATION (result); + if (tmp_perm.length ()) + { + lane_perm.safe_splice (tmp_perm); + SLP_TREE_CHILDREN (result).safe_splice (SLP_TREE_CHILDREN (node)); + } + else + { + lane_perm.create (num_lanes); + for (unsigned j = 0; j < num_lanes; ++j) + lane_perm.quick_push ({ 0, j }); + if (from_layout_i != 0) + vect_slp_permute (m_perms[from_layout_i], lane_perm, false); + if (to_layout_i != 0) + vect_slp_permute (m_perms[to_layout_i], lane_perm, true); + SLP_TREE_CHILDREN (result).safe_push (node); + } + for (slp_tree child : SLP_TREE_CHILDREN (result)) + child->refcnt++; + } + m_node_layouts[result_i] = result; + return result; +} + +/* Apply the chosen vector layouts to the SLP graph. */ +void +vect_optimize_slp_pass::materialize () +{ + /* We no longer need the costs, so avoid having two O(N * P) arrays + live at the same time. */ + m_partition_layout_costs.release (); + m_node_layouts.safe_grow_cleared (m_vertices.length () * m_perms.length ()); + + auto_sbitmap fully_folded (m_vertices.length ()); + bitmap_clear (fully_folded); + for (unsigned int node_i : m_partitioned_nodes) + { + auto &vertex = m_vertices[node_i]; + slp_tree node = vertex.node; + int layout_i = m_partitions[vertex.partition].layout; + gcc_assert (layout_i >= 0); + + /* Rearrange the scalar statements to match the chosen layout. */ + if (layout_i > 0) + vect_slp_permute (m_perms[layout_i], + SLP_TREE_SCALAR_STMTS (node), true); + + /* Update load and lane permutations. */ if (SLP_TREE_CODE (node) == VEC_PERM_EXPR) { - /* Apply the common permutes to the input vectors. */ - if (perm_in > 0) + /* First try to absorb the input vector layouts. If that fails, + force the inputs to have layout LAYOUT_I too. We checked that + that was possible before deciding to use nonzero output layouts. + (Note that at this stage we don't really have any guarantee that + the target supports the original VEC_PERM_EXPR.) */ + auto &perm = SLP_TREE_LANE_PERMUTATION (node); + auto_lane_permutation_t tmp_perm; + tmp_perm.safe_splice (perm); + change_vec_perm_layout (node, tmp_perm, -1, layout_i); + if (vectorizable_slp_permutation_1 (m_vinfo, nullptr, node, + tmp_perm, + SLP_TREE_CHILDREN (node), + false) >= 0) { - /* If the node is already a permute node we can apply - the permutation to the lane selection, effectively - materializing it on the incoming vectors. */ - if (dump_enabled_p ()) + if (dump_enabled_p () + && !std::equal (tmp_perm.begin (), tmp_perm.end (), + perm.begin ())) dump_printf_loc (MSG_NOTE, vect_location, - "simplifying permute node %p\n", - node); - for (unsigned k = 0; - k < SLP_TREE_LANE_PERMUTATION (node).length (); ++k) - SLP_TREE_LANE_PERMUTATION (node)[k].second - = perms[perm_in][SLP_TREE_LANE_PERMUTATION (node)[k].second]; - } - /* Apply the anticipated output permute to the permute and - stmt vectors. */ - int perm_out = vertices[i].perm_out; - if (perm_out > 0) - { - vect_slp_permute (perms[perm_out], - SLP_TREE_SCALAR_STMTS (node), true); - vect_slp_permute (perms[perm_out], - SLP_TREE_LANE_PERMUTATION (node), true); + "absorbing input layouts into %p\n", + (void *) node); + std::copy (tmp_perm.begin (), tmp_perm.end (), perm.begin ()); + bitmap_set_bit (fully_folded, node_i); } - } - else if (vertices[i].get_perm_materialized () != 0) - { - if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) - /* For loads simply drop the permutation, the load permutation - already performs the desired permutation. */ - ; - else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) - gcc_unreachable (); else { + /* Not MSG_MISSED because it would make no sense to users. */ if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "inserting permute node in place of %p\n", - node); - - /* Make a copy of NODE and in-place change it to a - VEC_PERM node to permute the lanes of the copy. */ - slp_tree copy = new _slp_tree; - SLP_TREE_CHILDREN (copy) = SLP_TREE_CHILDREN (node); - SLP_TREE_CHILDREN (node) = vNULL; - SLP_TREE_SCALAR_STMTS (copy) - = SLP_TREE_SCALAR_STMTS (node).copy (); - vect_slp_permute (perms[perm_in], - SLP_TREE_SCALAR_STMTS (copy), true); - gcc_assert (!SLP_TREE_SCALAR_OPS (node).exists ()); - SLP_TREE_REPRESENTATIVE (copy) = SLP_TREE_REPRESENTATIVE (node); - gcc_assert (!SLP_TREE_LOAD_PERMUTATION (node).exists ()); - SLP_TREE_LANE_PERMUTATION (copy) - = SLP_TREE_LANE_PERMUTATION (node); - SLP_TREE_LANE_PERMUTATION (node) = vNULL; - SLP_TREE_VECTYPE (copy) = SLP_TREE_VECTYPE (node); - copy->refcnt = 1; - copy->max_nunits = node->max_nunits; - SLP_TREE_DEF_TYPE (copy) = SLP_TREE_DEF_TYPE (node); - SLP_TREE_LANES (copy) = SLP_TREE_LANES (node); - SLP_TREE_CODE (copy) = SLP_TREE_CODE (node); - - /* Now turn NODE into a VEC_PERM. */ - SLP_TREE_CHILDREN (node).safe_push (copy); - SLP_TREE_LANE_PERMUTATION (node).create (SLP_TREE_LANES (node)); - for (unsigned j = 0; j < SLP_TREE_LANES (node); ++j) - SLP_TREE_LANE_PERMUTATION (node) - .quick_push (std::make_pair (0, perms[perm_in][j])); - SLP_TREE_CODE (node) = VEC_PERM_EXPR; + "failed to absorb input layouts into %p\n", + (void *) node); + change_vec_perm_layout (nullptr, perm, layout_i, layout_i); } } - else if (perm_in > 0) /* perm_in == perm_out */ + else { - /* Apply the reverse permutation to our stmts. */ - vect_slp_permute (perms[perm_in], - SLP_TREE_SCALAR_STMTS (node), true); - /* And to the lane/load permutation, which we can simply - make regular by design. */ - if (SLP_TREE_LOAD_PERMUTATION (node).exists ()) - { - gcc_assert (!SLP_TREE_LANE_PERMUTATION (node).exists ()); - /* ??? When we handle non-bijective permutes the idea - is that we can force the load-permutation to be - { min, min + 1, min + 2, ... max }. But then the - scalar defs might no longer match the lane content - which means wrong-code with live lane vectorization. - So we possibly have to have NULL entries for those. */ - vect_slp_permute (perms[perm_in], - SLP_TREE_LOAD_PERMUTATION (node), true); - } - else if (SLP_TREE_LANE_PERMUTATION (node).exists ()) - gcc_unreachable (); + gcc_assert (!SLP_TREE_LANE_PERMUTATION (node).exists ()); + auto &load_perm = SLP_TREE_LOAD_PERMUTATION (node); + if (layout_i > 0) + /* ??? When we handle non-bijective permutes the idea + is that we can force the load-permutation to be + { min, min + 1, min + 2, ... max }. But then the + scalar defs might no longer match the lane content + which means wrong-code with live lane vectorization. + So we possibly have to have NULL entries for those. */ + vect_slp_permute (m_perms[layout_i], load_perm, true); } } - /* Elide any permutations at BB reduction roots. */ - if (is_a <bb_vec_info> (vinfo)) + /* Do this before any nodes disappear, since it involves a walk + over the leaves. */ + remove_redundant_permutations (); + + /* Replace each child with a correctly laid-out version. */ + for (unsigned int node_i : m_partitioned_nodes) { - for (slp_instance instance : vinfo->slp_instances) + /* Skip nodes that have already been handled above. */ + if (bitmap_bit_p (fully_folded, node_i)) + continue; + + auto &vertex = m_vertices[node_i]; + int in_layout_i = m_partitions[vertex.partition].layout; + gcc_assert (in_layout_i >= 0); + + unsigned j; + slp_tree child; + FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (vertex.node), j, child) { - if (SLP_INSTANCE_KIND (instance) != slp_inst_kind_bb_reduc) + if (!child) continue; - slp_tree old = SLP_INSTANCE_TREE (instance); - if (SLP_TREE_CODE (old) == VEC_PERM_EXPR - && SLP_TREE_CHILDREN (old).length () == 1) - { - slp_tree child = SLP_TREE_CHILDREN (old)[0]; - if (SLP_TREE_DEF_TYPE (child) == vect_external_def) - { - /* Preserve the special VEC_PERM we use to shield existing - vector defs from the rest. But make it a no-op. */ - unsigned i = 0; - for (std::pair<unsigned, unsigned> &p - : SLP_TREE_LANE_PERMUTATION (old)) - p.second = i++; - } - else - { - SLP_INSTANCE_TREE (instance) = child; - SLP_TREE_REF_COUNT (child)++; - vect_free_slp_tree (old); - } - } - else if (SLP_TREE_LOAD_PERMUTATION (old).exists () - && SLP_TREE_REF_COUNT (old) == 1 - && vertices[old->vertex].get_perm_materialized () != 0) + + slp_tree new_child = get_result_with_layout (child, in_layout_i); + if (new_child != child) { - /* ??? For loads the situation is more complex since - we can't modify the permute in place in case the - node is used multiple times. In fact for loads this - should be somehow handled in the propagation engine. */ - /* Apply the reverse permutation to our stmts. */ - int perm = vertices[old->vertex].get_perm_materialized (); - vect_slp_permute (perms[perm], - SLP_TREE_SCALAR_STMTS (old), true); - vect_slp_permute (perms[perm], - SLP_TREE_LOAD_PERMUTATION (old), true); + vect_free_slp_tree (child); + SLP_TREE_CHILDREN (vertex.node)[j] = new_child; + new_child->refcnt += 1; } } } +} - /* Free the perms vector used for propagation. */ - while (!perms.is_empty ()) - perms.pop ().release (); - free_graph (slpg); - +/* Elide load permutations that are not necessary. Such permutations might + be pre-existing, rather than created by the layout optimizations. */ - /* Now elide load permutations that are not necessary. */ - for (i = 0; i < leafs.length (); ++i) +void +vect_optimize_slp_pass::remove_redundant_permutations () +{ + for (unsigned int node_i : m_leafs) { - node = vertices[leafs[i]].node; + slp_tree node = m_vertices[node_i].node; if (!SLP_TREE_LOAD_PERMUTATION (node).exists ()) continue; /* In basic block vectorization we allow any subchain of an interleaving chain. FORNOW: not in loop SLP because of realignment complications. */ - if (is_a <bb_vec_info> (vinfo)) + if (is_a <bb_vec_info> (m_vinfo)) { bool subchain_p = true; stmt_vec_info next_load_info = NULL; @@ -4160,6 +5395,7 @@ vect_optimize_slp (vec_info *vinfo) } else { + loop_vec_info loop_vinfo = as_a<loop_vec_info> (m_vinfo); stmt_vec_info load_info; bool this_load_permuted = false; unsigned j; @@ -4175,8 +5411,7 @@ vect_optimize_slp (vec_info *vinfo) /* The load requires permutation when unrolling exposes a gap either because the group is larger than the SLP group-size or because there is a gap between the groups. */ - && (known_eq (LOOP_VINFO_VECT_FACTOR - (as_a <loop_vec_info> (vinfo)), 1U) + && (known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), 1U) || ((SLP_TREE_LANES (node) == DR_GROUP_SIZE (first_stmt_info)) && DR_GROUP_GAP (first_stmt_info) == 0))) { @@ -4187,6 +5422,152 @@ vect_optimize_slp (vec_info *vinfo) } } +/* Print the partition graph and layout information to the dump file. */ + +void +vect_optimize_slp_pass::dump () +{ + dump_printf_loc (MSG_NOTE, vect_location, + "SLP optimize permutations:\n"); + for (unsigned int layout_i = 1; layout_i < m_perms.length (); ++layout_i) + { + dump_printf_loc (MSG_NOTE, vect_location, " %d: { ", layout_i); + const char *sep = ""; + for (unsigned int idx : m_perms[layout_i]) + { + dump_printf (MSG_NOTE, "%s%d", sep, idx); + sep = ", "; + } + dump_printf (MSG_NOTE, " }\n"); + } + dump_printf_loc (MSG_NOTE, vect_location, + "SLP optimize partitions:\n"); + for (unsigned int partition_i = 0; partition_i < m_partitions.length (); + ++partition_i) + { + auto &partition = m_partitions[partition_i]; + dump_printf_loc (MSG_NOTE, vect_location, " -------------\n"); + dump_printf_loc (MSG_NOTE, vect_location, + " partition %d (layout %d):\n", + partition_i, partition.layout); + dump_printf_loc (MSG_NOTE, vect_location, " nodes:\n"); + for (unsigned int order_i = partition.node_begin; + order_i < partition.node_end; ++order_i) + { + auto &vertex = m_vertices[m_partitioned_nodes[order_i]]; + dump_printf_loc (MSG_NOTE, vect_location, " - %p:\n", + (void *) vertex.node); + dump_printf_loc (MSG_NOTE, vect_location, + " weight: %f\n", + vertex.weight.to_double ()); + if (vertex.out_degree) + dump_printf_loc (MSG_NOTE, vect_location, + " out weight: %f (degree %d)\n", + vertex.out_weight.to_double (), + vertex.out_degree); + if (SLP_TREE_CODE (vertex.node) == VEC_PERM_EXPR) + dump_printf_loc (MSG_NOTE, vect_location, + " op: VEC_PERM_EXPR\n"); + else if (auto rep = SLP_TREE_REPRESENTATIVE (vertex.node)) + dump_printf_loc (MSG_NOTE, vect_location, + " op template: %G", rep->stmt); + } + dump_printf_loc (MSG_NOTE, vect_location, " edges:\n"); + for (unsigned int order_i = partition.node_begin; + order_i < partition.node_end; ++order_i) + { + unsigned int node_i = m_partitioned_nodes[order_i]; + auto &vertex = m_vertices[node_i]; + auto print_edge = [&](graph_edge *, unsigned int other_node_i) + { + auto &other_vertex = m_vertices[other_node_i]; + if (other_vertex.partition < vertex.partition) + dump_printf_loc (MSG_NOTE, vect_location, + " - %p [%d] --> %p\n", + (void *) other_vertex.node, + other_vertex.partition, + (void *) vertex.node); + else + dump_printf_loc (MSG_NOTE, vect_location, + " - %p --> [%d] %p\n", + (void *) vertex.node, + other_vertex.partition, + (void *) other_vertex.node); + }; + for_each_partition_edge (node_i, print_edge); + } + + for (unsigned int layout_i = 0; layout_i < m_perms.length (); ++layout_i) + { + auto &layout_costs = partition_layout_costs (partition_i, layout_i); + if (layout_costs.is_possible ()) + { + dump_printf_loc (MSG_NOTE, vect_location, + " layout %d:%s\n", layout_i, + partition.layout == int (layout_i) + ? " (*)" : ""); + slpg_layout_cost combined_cost = layout_costs.in_cost; + combined_cost.add_serial_cost (layout_costs.internal_cost); + combined_cost.add_serial_cost (layout_costs.out_cost); +#define TEMPLATE "{depth: %f, total: %f}" + dump_printf_loc (MSG_NOTE, vect_location, + " " TEMPLATE "\n", + layout_costs.in_cost.depth.to_double (), + layout_costs.in_cost.total.to_double ()); + dump_printf_loc (MSG_NOTE, vect_location, + " + " TEMPLATE "\n", + layout_costs.internal_cost.depth.to_double (), + layout_costs.internal_cost.total.to_double ()); + dump_printf_loc (MSG_NOTE, vect_location, + " + " TEMPLATE "\n", + layout_costs.out_cost.depth.to_double (), + layout_costs.out_cost.total.to_double ()); + dump_printf_loc (MSG_NOTE, vect_location, + " = " TEMPLATE "\n", + combined_cost.depth.to_double (), + combined_cost.total.to_double ()); +#undef TEMPLATE + } + else + dump_printf_loc (MSG_NOTE, vect_location, + " layout %d: rejected\n", layout_i); + } + } +} + +/* Main entry point for the SLP graph optimization pass. */ + +void +vect_optimize_slp_pass::run () +{ + build_graph (); + create_partitions (); + start_choosing_layouts (); + if (m_perms.length () > 1) + { + forward_pass (); + backward_pass (); + if (dump_enabled_p ()) + dump (); + materialize (); + while (!m_perms.is_empty ()) + m_perms.pop ().release (); + } + else + remove_redundant_permutations (); + free_graph (m_slpg); +} + +/* Optimize the SLP graph of VINFO. */ + +void +vect_optimize_slp (vec_info *vinfo) +{ + if (vinfo->slp_instances.is_empty ()) + return; + vect_optimize_slp_pass (vinfo).run (); +} + /* Gather loads reachable from the individual SLP graph entries. */ void @@ -4555,7 +5936,8 @@ vect_slp_convert_to_external (vec_info *vinfo, slp_tree node, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "Building vector operands of %p from scalars instead\n", node); + "Building vector operands of %p from scalars instead\n", + (void *) node); /* Don't remove and free the child nodes here, since they could be referenced by other structures. The analysis and scheduling phases @@ -4682,7 +6064,7 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "Failed cyclic SLP reference in %p\n", node); + "Failed cyclic SLP reference in %p\n", (void *) node); return false; } gcc_assert (SLP_TREE_DEF_TYPE (node) == vect_internal_def); @@ -4714,7 +6096,8 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node, { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "Cannot vectorize all-constant op node %p\n", node); + "Cannot vectorize all-constant op node %p\n", + (void *) node); res = false; } @@ -5072,47 +6455,64 @@ get_ultimate_leader (slp_instance instance, return instance; } +namespace { +/* Subroutine of vect_bb_partition_graph_r. Map KEY to INSTANCE in + KEY_TO_INSTANCE, making INSTANCE the leader of any previous mapping + for KEY. Return true if KEY was already in KEY_TO_INSTANCE. + + INSTANCE_LEADER is as for get_ultimate_leader. */ + +template<typename T> +bool +vect_map_to_instance (slp_instance instance, T key, + hash_map<T, slp_instance> &key_to_instance, + hash_map<slp_instance, slp_instance> &instance_leader) +{ + bool existed_p; + slp_instance &key_instance = key_to_instance.get_or_insert (key, &existed_p); + if (!existed_p) + ; + else if (key_instance != instance) + { + /* If we're running into a previously marked key make us the + leader of the current ultimate leader. This keeps the + leader chain acyclic and works even when the current instance + connects two previously independent graph parts. */ + slp_instance key_leader + = get_ultimate_leader (key_instance, instance_leader); + if (key_leader != instance) + instance_leader.put (key_leader, instance); + } + key_instance = instance; + return existed_p; +} +} + /* Worker of vect_bb_partition_graph, recurse on NODE. */ static void vect_bb_partition_graph_r (bb_vec_info bb_vinfo, slp_instance instance, slp_tree node, hash_map<stmt_vec_info, slp_instance> &stmt_to_instance, - hash_map<slp_instance, slp_instance> &instance_leader, - hash_set<slp_tree> &visited) + hash_map<slp_tree, slp_instance> &node_to_instance, + hash_map<slp_instance, slp_instance> &instance_leader) { stmt_vec_info stmt_info; unsigned i; FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, stmt_info) - { - bool existed_p; - slp_instance &stmt_instance - = stmt_to_instance.get_or_insert (stmt_info, &existed_p); - if (!existed_p) - ; - else if (stmt_instance != instance) - { - /* If we're running into a previously marked stmt make us the - leader of the current ultimate leader. This keeps the - leader chain acyclic and works even when the current instance - connects two previously independent graph parts. */ - slp_instance stmt_leader - = get_ultimate_leader (stmt_instance, instance_leader); - if (stmt_leader != instance) - instance_leader.put (stmt_leader, instance); - } - stmt_instance = instance; - } + vect_map_to_instance (instance, stmt_info, stmt_to_instance, + instance_leader); - if (!SLP_TREE_SCALAR_STMTS (node).is_empty () && visited.add (node)) + if (vect_map_to_instance (instance, node, node_to_instance, + instance_leader)) return; slp_tree child; FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) if (child && SLP_TREE_DEF_TYPE (child) == vect_internal_def) vect_bb_partition_graph_r (bb_vinfo, instance, child, stmt_to_instance, - instance_leader, visited); + node_to_instance, instance_leader); } /* Partition the SLP graph into pieces that can be costed independently. */ @@ -5126,16 +6526,16 @@ vect_bb_partition_graph (bb_vec_info bb_vinfo) corresponding SLP graph entry and upon visiting a previously marked stmt, make the stmts leader the current SLP graph entry. */ hash_map<stmt_vec_info, slp_instance> stmt_to_instance; + hash_map<slp_tree, slp_instance> node_to_instance; hash_map<slp_instance, slp_instance> instance_leader; - hash_set<slp_tree> visited; slp_instance instance; for (unsigned i = 0; bb_vinfo->slp_instances.iterate (i, &instance); ++i) { instance_leader.put (instance, instance); vect_bb_partition_graph_r (bb_vinfo, instance, SLP_INSTANCE_TREE (instance), - stmt_to_instance, instance_leader, - visited); + stmt_to_instance, node_to_instance, + instance_leader); } /* Then collect entries to each independent subgraph. */ @@ -5147,7 +6547,7 @@ vect_bb_partition_graph (bb_vec_info bb_vinfo) && leader != instance) dump_printf_loc (MSG_NOTE, vect_location, "instance %p is leader of %p\n", - leader, instance); + (void *) leader, (void *) instance); } } @@ -6631,23 +8031,23 @@ vect_get_slp_defs (vec_info *, } } -/* Generate vector permute statements from a list of loads in DR_CHAIN. - If ANALYZE_ONLY is TRUE, only check that it is possible to create valid - permute statements for the SLP node NODE. Store the number of vector - permute instructions in *N_PERMS and the number of vector load - instructions in *N_LOADS. If DCE_CHAIN is true, remove all definitions - that were not needed. */ +/* A subroutine of vect_transform_slp_perm_load with two extra arguments: + - PERM gives the permutation that the caller wants to use for NODE, + which might be different from SLP_LOAD_PERMUTATION. + - DUMP_P controls whether the function dumps information. */ -bool -vect_transform_slp_perm_load (vec_info *vinfo, - slp_tree node, const vec<tree> &dr_chain, - gimple_stmt_iterator *gsi, poly_uint64 vf, - bool analyze_only, unsigned *n_perms, - unsigned int *n_loads, bool dce_chain) +static bool +vect_transform_slp_perm_load_1 (vec_info *vinfo, slp_tree node, + load_permutation_t &perm, + const vec<tree> &dr_chain, + gimple_stmt_iterator *gsi, poly_uint64 vf, + bool analyze_only, bool dump_p, + unsigned *n_perms, unsigned int *n_loads, + bool dce_chain) { stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0]; int vec_index = 0; - tree vectype = STMT_VINFO_VECTYPE (stmt_info); + tree vectype = SLP_TREE_VECTYPE (node); unsigned int group_size = SLP_TREE_SCALAR_STMTS (node).length (); unsigned int mask_element; machine_mode mode; @@ -6732,8 +8132,7 @@ vect_transform_slp_perm_load (vec_info *vinfo, { unsigned int iter_num = j / group_size; unsigned int stmt_num = j % group_size; - unsigned int i = (iter_num * DR_GROUP_SIZE (stmt_info) - + SLP_TREE_LOAD_PERMUTATION (node)[stmt_num]); + unsigned int i = (iter_num * DR_GROUP_SIZE (stmt_info) + perm[stmt_num]); bitmap_set_bit (used_in_lanes, i); if (repeating_p) { @@ -6759,7 +8158,7 @@ vect_transform_slp_perm_load (vec_info *vinfo, } else { - if (dump_enabled_p ()) + if (dump_p) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "permutation requires at " "least three vectors %G", @@ -6780,7 +8179,7 @@ vect_transform_slp_perm_load (vec_info *vinfo, indices.new_vector (mask, second_vec_index == -1 ? 1 : 2, nunits); if (!can_vec_perm_const_p (mode, mode, indices)) { - if (dump_enabled_p ()) + if (dump_p) { dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -6896,6 +8295,27 @@ vect_transform_slp_perm_load (vec_info *vinfo, return true; } +/* Generate vector permute statements from a list of loads in DR_CHAIN. + If ANALYZE_ONLY is TRUE, only check that it is possible to create valid + permute statements for the SLP node NODE. Store the number of vector + permute instructions in *N_PERMS and the number of vector load + instructions in *N_LOADS. If DCE_CHAIN is true, remove all definitions + that were not needed. */ + +bool +vect_transform_slp_perm_load (vec_info *vinfo, + slp_tree node, const vec<tree> &dr_chain, + gimple_stmt_iterator *gsi, poly_uint64 vf, + bool analyze_only, unsigned *n_perms, + unsigned int *n_loads, bool dce_chain) +{ + return vect_transform_slp_perm_load_1 (vinfo, node, + SLP_TREE_LOAD_PERMUTATION (node), + dr_chain, gsi, vf, analyze_only, + dump_enabled_p (), n_perms, n_loads, + dce_chain); +} + /* Produce the next vector result for SLP permutation NODE by adding a vector statement at GSI. If MASK_VEC is nonnull, add: @@ -6976,20 +8396,22 @@ vect_add_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, SLP_TREE_VEC_STMTS (node).quick_push (perm_stmt); } -/* Vectorize the SLP permutations in NODE as specified - in SLP_TREE_LANE_PERMUTATION which is a vector of pairs of SLP - child number and lane number. - Interleaving of two two-lane two-child SLP subtrees (not supported): - [ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } ] - A blend of two four-lane two-child SLP subtrees: - [ { 0, 0 }, { 1, 1 }, { 0, 2 }, { 1, 3 } ] - Highpart of a four-lane one-child SLP subtree (not supported): - [ { 0, 2 }, { 0, 3 } ] - Where currently only a subset is supported by code generating below. */ +/* Subroutine of vectorizable_slp_permutation. Check whether the target + can perform permutation PERM on the (1 or 2) input nodes in CHILDREN. + If GSI is nonnull, emit the permutation there. -static bool -vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, - slp_tree node, stmt_vector_for_cost *cost_vec) + When GSI is null, the only purpose of NODE is to give properties + of the result, such as the vector type and number of SLP lanes. + The node does not need to be a VEC_PERM_EXPR. + + If the target supports the operation, return the number of individual + VEC_PERM_EXPRs needed, otherwise return -1. Print information to the + dump file if DUMP_P is true. */ + +static int +vectorizable_slp_permutation_1 (vec_info *vinfo, gimple_stmt_iterator *gsi, + slp_tree node, lane_permutation_t &perm, + vec<slp_tree> &children, bool dump_p) { tree vectype = SLP_TREE_VECTYPE (node); @@ -7001,7 +8423,7 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype); bool repeating_p = multiple_p (nunits, SLP_TREE_LANES (node)); tree op_vectype = NULL_TREE; - FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) + FOR_EACH_VEC_ELT (children, i, child) if (SLP_TREE_VECTYPE (child)) { op_vectype = SLP_TREE_VECTYPE (child); @@ -7009,25 +8431,24 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, } if (!op_vectype) op_vectype = vectype; - FOR_EACH_VEC_ELT (SLP_TREE_CHILDREN (node), i, child) + FOR_EACH_VEC_ELT (children, i, child) { if ((SLP_TREE_DEF_TYPE (child) != vect_internal_def && !vect_maybe_update_slp_op_vectype (child, op_vectype)) || !types_compatible_p (SLP_TREE_VECTYPE (child), op_vectype) || !types_compatible_p (TREE_TYPE (vectype), TREE_TYPE (op_vectype))) { - if (dump_enabled_p ()) + if (dump_p) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "Unsupported vector types in lane permutation\n"); - return false; + return -1; } if (SLP_TREE_LANES (child) != SLP_TREE_LANES (node)) repeating_p = false; } - vec<std::pair<unsigned, unsigned> > &perm = SLP_TREE_LANE_PERMUTATION (node); gcc_assert (perm.length () == SLP_TREE_LANES (node)); - if (dump_enabled_p ()) + if (dump_p) { dump_printf_loc (MSG_NOTE, vect_location, "vectorizing permutation"); @@ -7076,11 +8497,11 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, /* Calculate every element of every permute mask vector explicitly, instead of relying on the pattern described above. */ if (!nunits.is_constant (&npatterns)) - return false; + return -1; nelts_per_pattern = ncopies = 1; if (loop_vec_info linfo = dyn_cast <loop_vec_info> (vinfo)) if (!LOOP_VINFO_VECT_FACTOR (linfo).is_constant (&ncopies)) - return false; + return -1; noutputs_per_mask = 1; } unsigned olanes = ncopies * SLP_TREE_LANES (node); @@ -7093,13 +8514,13 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, auto_vec<std::pair<std::pair<unsigned, unsigned>, unsigned> > vperm; auto_vec<unsigned> active_lane; vperm.create (olanes); - active_lane.safe_grow_cleared (SLP_TREE_CHILDREN (node).length (), true); + active_lane.safe_grow_cleared (children.length (), true); for (unsigned i = 0; i < ncopies; ++i) { for (unsigned pi = 0; pi < perm.length (); ++pi) { std::pair<unsigned, unsigned> p = perm[pi]; - tree vtype = SLP_TREE_VECTYPE (SLP_TREE_CHILDREN (node)[p.first]); + tree vtype = SLP_TREE_VECTYPE (children[p.first]); if (repeating_p) vperm.quick_push ({{p.first, 0}, p.second + active_lane[p.first]}); else @@ -7112,12 +8533,19 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, } } /* Advance to the next group. */ - for (unsigned j = 0; j < SLP_TREE_CHILDREN (node).length (); ++j) - active_lane[j] += SLP_TREE_LANES (SLP_TREE_CHILDREN (node)[j]); + for (unsigned j = 0; j < children.length (); ++j) + active_lane[j] += SLP_TREE_LANES (children[j]); } - if (dump_enabled_p ()) + if (dump_p) { + dump_printf_loc (MSG_NOTE, vect_location, + "vectorizing permutation"); + for (unsigned i = 0; i < perm.length (); ++i) + dump_printf (MSG_NOTE, " op%u[%u]", perm[i].first, perm[i].second); + if (repeating_p) + dump_printf (MSG_NOTE, " (repeat %d)\n", SLP_TREE_LANES (node)); + dump_printf (MSG_NOTE, "\n"); dump_printf_loc (MSG_NOTE, vect_location, "as"); for (unsigned i = 0; i < vperm.length (); ++i) { @@ -7163,12 +8591,12 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, } else { - if (dump_enabled_p ()) + if (dump_p) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "permutation requires at " "least three vectors\n"); gcc_assert (!gsi); - return false; + return -1; } mask[index++] = mask_element; @@ -7190,7 +8618,7 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, TYPE_VECTOR_SUBPARTS (op_vectype), &c) || c != 2))) { - if (dump_enabled_p ()) + if (dump_p) { dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -7203,7 +8631,7 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, dump_printf (MSG_MISSED_OPTIMIZATION, "}\n"); } gcc_assert (!gsi); - return false; + return -1; } if (!identity_p) @@ -7214,8 +8642,8 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, second_vec = first_vec; slp_tree - first_node = SLP_TREE_CHILDREN (node)[first_vec.first], - second_node = SLP_TREE_CHILDREN (node)[second_vec.first]; + first_node = children[first_vec.first], + second_node = children[second_vec.first]; tree mask_vec = NULL_TREE; if (!identity_p) @@ -7240,6 +8668,32 @@ vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, } } + return nperms; +} + +/* Vectorize the SLP permutations in NODE as specified + in SLP_TREE_LANE_PERMUTATION which is a vector of pairs of SLP + child number and lane number. + Interleaving of two two-lane two-child SLP subtrees (not supported): + [ { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } ] + A blend of two four-lane two-child SLP subtrees: + [ { 0, 0 }, { 1, 1 }, { 0, 2 }, { 1, 3 } ] + Highpart of a four-lane one-child SLP subtree (not supported): + [ { 0, 2 }, { 0, 3 } ] + Where currently only a subset is supported by code generating below. */ + +static bool +vectorizable_slp_permutation (vec_info *vinfo, gimple_stmt_iterator *gsi, + slp_tree node, stmt_vector_for_cost *cost_vec) +{ + tree vectype = SLP_TREE_VECTYPE (node); + lane_permutation_t &perm = SLP_TREE_LANE_PERMUTATION (node); + int nperms = vectorizable_slp_permutation_1 (vinfo, gsi, node, perm, + SLP_TREE_CHILDREN (node), + dump_enabled_p ()); + if (nperms < 0) + return false; + if (!gsi) record_stmt_cost (cost_vec, nperms, vec_perm, node, vectype, 0, vect_body); diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index c9dab21..c8d1efc 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -9042,7 +9042,8 @@ vectorizable_load (vec_info *vinfo, gassign *stmt = as_a <gassign *> (stmt_info->stmt); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, - "hoisting out of the vectorized loop: %G", stmt); + "hoisting out of the vectorized loop: %G", + (gimple *) stmt); scalar_dest = copy_ssa_name (scalar_dest); tree rhs = unshare_expr (gimple_assign_rhs1 (stmt)); edge pe = loop_preheader_edge (loop); @@ -11486,6 +11487,16 @@ get_related_vectype_for_scalar_type (machine_mode prevailing_mode, unsigned int nbytes = GET_MODE_SIZE (inner_mode); + /* Interoperability between modes requires one to be a constant multiple + of the other, so that the number of vectors required for each operation + is a compile-time constant. */ + if (prevailing_mode != VOIDmode + && !constant_multiple_p (nunits * nbytes, + GET_MODE_SIZE (prevailing_mode)) + && !constant_multiple_p (GET_MODE_SIZE (prevailing_mode), + nunits * nbytes)) + return NULL_TREE; + /* For vector types of elements whose mode precision doesn't match their types precision we use a element type of mode precision. The vectorization routines will have to make sure diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index e5fdc9e..a2b0afb 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -154,7 +154,9 @@ struct vect_scalar_ops_slice_hash : typed_noop_remove<vect_scalar_ops_slice> SLP ************************************************************************/ typedef vec<std::pair<unsigned, unsigned> > lane_permutation_t; +typedef auto_vec<std::pair<unsigned, unsigned>, 16> auto_lane_permutation_t; typedef vec<unsigned> load_permutation_t; +typedef auto_vec<unsigned, 16> auto_load_permutation_t; /* A computation tree of an SLP instance. Each node corresponds to a group of stmts to be packed in a SIMD stmt. */ diff --git a/gcc/tree.cc b/gcc/tree.cc index fed1434..2f488e4 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -294,6 +294,7 @@ unsigned const char omp_clause_num_ops[] = 2, /* OMP_CLAUSE_TO */ 2, /* OMP_CLAUSE_MAP */ 1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */ + 1, /* OMP_CLAUSE_DOACROSS */ 2, /* OMP_CLAUSE__CACHE_ */ 2, /* OMP_CLAUSE_GANG */ 1, /* OMP_CLAUSE_ASYNC */ @@ -384,6 +385,7 @@ const char * const omp_clause_code_name[] = "to", "map", "has_device_addr", + "doacross", "_cache_", "gang", "async", @@ -2385,12 +2387,12 @@ build_real (tree type, REAL_VALUE_TYPE d) tree v; int overflow = 0; - /* dconst{1,2,m1,half} are used in various places in + /* dconst{0,1,2,m1,half} are used in various places in the middle-end and optimizers, allow them here even for decimal floating point types as an exception by converting them to decimal. */ if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)) - && d.cl == rvc_normal + && (d.cl == rvc_normal || d.cl == rvc_zero) && !d.decimal) { if (memcmp (&d, &dconst1, sizeof (d)) == 0) @@ -2401,6 +2403,15 @@ build_real (tree type, REAL_VALUE_TYPE d) decimal_real_from_string (&d, "-1"); else if (memcmp (&d, &dconsthalf, sizeof (d)) == 0) decimal_real_from_string (&d, "0.5"); + else if (memcmp (&d, &dconst0, sizeof (d)) == 0) + { + /* Make sure to give zero the minimum quantum exponent for + the type (which corresponds to all bits zero). */ + const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type)); + char buf[16]; + sprintf (buf, "0e%d", fmt->emin - fmt->p); + decimal_real_from_string (&d, buf); + } else gcc_unreachable (); } @@ -2526,11 +2537,10 @@ build_complex (tree type, tree real, tree imag) tree build_complex_inf (tree type, bool neg) { - REAL_VALUE_TYPE rinf, rzero = dconst0; + REAL_VALUE_TYPE rzero = dconst0; - real_inf (&rinf); rzero.sign = neg; - return build_complex (type, build_real (TREE_TYPE (type), rinf), + return build_complex (type, build_real (TREE_TYPE (type), dconstinf), build_real (TREE_TYPE (type), rzero)); } @@ -1722,9 +1722,16 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_DEPEND_KIND(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEPEND)->omp_clause.subcode.depend_kind) -#define OMP_CLAUSE_DEPEND_SINK_NEGATIVE(NODE) \ +#define OMP_CLAUSE_DOACROSS_KIND(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)->omp_clause.subcode.doacross_kind) + +#define OMP_CLAUSE_DOACROSS_SINK_NEGATIVE(NODE) \ TREE_PUBLIC (TREE_LIST_CHECK (NODE)) +/* True if DOACROSS clause is spelled as DEPEND. */ +#define OMP_CLAUSE_DOACROSS_DEPEND(NODE) \ + TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DOACROSS)) + #define OMP_CLAUSE_MAP_KIND(NODE) \ ((enum gomp_map_kind) OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind) #define OMP_CLAUSE_SET_MAP_KIND(NODE, MAP_KIND) \ @@ -1786,6 +1793,11 @@ class auto_suppress_location_wrappers #define OMP_CLAUSE_ORDERED_EXPR(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0) +/* True on an OMP_CLAUSE_ORDERED if stand-alone ordered construct is nested + inside of work-sharing loop the clause is on. */ +#define OMP_CLAUSE_ORDERED_DOACROSS(NODE) \ + (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED)->base.public_flag) + /* True for unconstrained modifier on order(concurrent) clause. */ #define OMP_CLAUSE_ORDER_UNCONSTRAINED(NODE) \ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER)->base.public_flag) diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 4af8eca..201f679 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -211,12 +211,32 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt) switch (TREE_CODE (expr)) { case INTEGER_CST: - case REAL_CST: if (TREE_OVERFLOW_P (expr)) expr = drop_tree_overflow (expr); r.set (expr, expr); return true; + case REAL_CST: + { + if (TREE_OVERFLOW_P (expr)) + expr = drop_tree_overflow (expr); + + frange &f = as_a <frange> (r); + f.set (expr, expr); + + // Singletons from the tree world have known properties. + REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (expr); + if (real_isnan (rv)) + f.set_nan (fp_prop::YES); + else + f.set_nan (fp_prop::NO); + if (real_isneg (rv)) + f.set_signbit (fp_prop::YES); + else + f.set_signbit (fp_prop::NO); + return true; + } + case SSA_NAME: gimple_range_global (r, expr); return true; diff --git a/gcc/value-range-pretty-print.cc b/gcc/value-range-pretty-print.cc index cbf50d3..93e18d3 100644 --- a/gcc/value-range-pretty-print.cc +++ b/gcc/value-range-pretty-print.cc @@ -122,22 +122,31 @@ vrange_printer::print_irange_bitmasks (const irange &r) const void vrange_printer::visit (const frange &r) const { + tree type = r.type (); + pp_string (pp, "[frange] "); if (r.undefined_p ()) { pp_string (pp, "UNDEFINED"); return; } - dump_generic_node (pp, r.type (), 0, TDF_NONE, false); + dump_generic_node (pp, type, 0, TDF_NONE, false); pp_string (pp, " "); if (r.varying_p ()) { pp_string (pp, "VARYING"); return; } + pp_character (pp, '['); + dump_generic_node (pp, + build_real (type, r.lower_bound ()), 0, TDF_NONE, false); + pp_string (pp, ", "); + dump_generic_node (pp, + build_real (type, r.upper_bound ()), 0, TDF_NONE, false); + pp_string (pp, "] "); + print_frange_prop ("NAN", r.get_nan ()); - print_frange_prop ("INF", r.get_inf ()); - print_frange_prop ("NINF", r.get_ninf ()); + print_frange_prop ("SIGN", r.get_signbit ()); } // Print the FP properties in an frange. diff --git a/gcc/value-range-storage.cc b/gcc/value-range-storage.cc index ea3b83c..b7a23fa 100644 --- a/gcc/value-range-storage.cc +++ b/gcc/value-range-storage.cc @@ -253,6 +253,8 @@ frange_storage_slot::set_frange (const frange &r) gcc_checking_assert (fits_p (r)); gcc_checking_assert (!r.undefined_p ()); + m_min = r.m_min; + m_max = r.m_max; m_props = r.m_props; } @@ -261,8 +263,12 @@ frange_storage_slot::get_frange (frange &r, tree type) const { gcc_checking_assert (r.supports_type_p (type)); - r.set_varying (type); + r.set_undefined (); + r.m_kind = VR_RANGE; r.m_props = m_props; + r.m_type = type; + r.m_min = m_min; + r.m_max = m_max; r.normalize_kind (); if (flag_checking) diff --git a/gcc/value-range-storage.h b/gcc/value-range-storage.h index 9cd6b9f..f506789 100644 --- a/gcc/value-range-storage.h +++ b/gcc/value-range-storage.h @@ -113,9 +113,11 @@ class GTY (()) frange_storage_slot frange_storage_slot (const frange &r) { set_frange (r); } DISABLE_COPY_AND_ASSIGN (frange_storage_slot); - // We can get away with just storing the properties because the type - // can be gotten from the SSA, and UNDEFINED is unsupported, so it - // can only be a range. + // We can get away with just storing the properties and the + // endpoints because the type can be gotten from the SSA, and + // UNDEFINED is unsupported, so it can only be a VR_RANGE. + REAL_VALUE_TYPE m_min; + REAL_VALUE_TYPE m_max; frange_props m_props; }; diff --git a/gcc/value-range.cc b/gcc/value-range.cc index d056f73..9c56141 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -94,8 +94,9 @@ vrange::singleton_p (tree *) const } void -vrange::set (tree, tree, value_range_kind) +vrange::set (tree min, tree, value_range_kind) { + set_varying (TREE_TYPE (min)); } tree @@ -168,18 +169,21 @@ vrange::nonzero_p () const } void -vrange::set_nonzero (tree) +vrange::set_nonzero (tree type) { + set_varying (type); } void -vrange::set_zero (tree) +vrange::set_zero (tree type) { + set_varying (type); } void -vrange::set_nonnegative (tree) +vrange::set_nonnegative (tree type) { + set_varying (type); } bool @@ -263,6 +267,77 @@ tree_compare (tree_code code, tree op1, tree op2) return !integer_zerop (fold_build2 (code, integer_type_node, op1, op2)); } +// Set the NAN property. Adjust the range if appopriate. + +void +frange::set_nan (fp_prop::kind k) +{ + if (k == fp_prop::YES) + { + gcc_checking_assert (!undefined_p ()); + *this = frange_nan (m_type); + return; + } + + // Setting NO on an obviously NAN range is nonsensical. + gcc_checking_assert (k != fp_prop::NO || !real_isnan (&m_min)); + + // Setting VARYING on an obviously NAN range is a no-op. + if (k == fp_prop::VARYING && real_isnan (&m_min)) + return; + + m_props.set_nan (k); + normalize_kind (); + if (flag_checking) + verify_range (); +} + +// Set the SIGNBIT property. Adjust the range if appropriate. + +void +frange::set_signbit (fp_prop::kind k) +{ + gcc_checking_assert (m_type); + + // No additional adjustments are needed for a NAN. + if (get_nan ().yes_p ()) + { + m_props.set_signbit (k); + return; + } + // Ignore sign changes when they're set correctly. + if (real_less (&m_max, &dconst0)) + { + gcc_checking_assert (get_signbit ().yes_p ()); + return; + } + if (real_less (&dconst0, &m_min)) + { + gcc_checking_assert (get_signbit ().no_p ()); + return; + } + // Adjust the range depending on the sign bit. + if (k == fp_prop::YES) + { + // Crop the range to [-INF, 0]. + frange crop (m_type, dconstninf, dconst0); + intersect (crop); + m_props.set_signbit (fp_prop::YES); + } + else if (k == fp_prop::NO) + { + // Crop the range to [0, +INF]. + frange crop (m_type, dconst0, dconstinf); + intersect (crop); + m_props.set_signbit (fp_prop::NO); + } + else + m_props.set_signbit (fp_prop::VARYING); + + if (flag_checking) + verify_range (); +} + // Setter for franges. void @@ -287,41 +362,26 @@ frange::set (tree min, tree max, value_range_kind kind) m_kind = kind; m_type = TREE_TYPE (min); m_props.set_varying (); + m_min = *TREE_REAL_CST_PTR (min); + m_max = *TREE_REAL_CST_PTR (max); - bool is_min = vrp_val_is_min (min); - bool is_max = vrp_val_is_max (max); bool is_nan = (real_isnan (TREE_REAL_CST_PTR (min)) || real_isnan (TREE_REAL_CST_PTR (max))); // Ranges with a NAN and a non-NAN endpoint are nonsensical. gcc_checking_assert (!is_nan || operand_equal_p (min, max)); - // The properties for singletons can be all set ahead of time. - if (operand_equal_p (min, max)) - { - // Set INF properties. - if (is_min) - m_props.ninf_set_yes (); - else - m_props.ninf_set_no (); - if (is_max) - m_props.inf_set_yes (); - else - m_props.inf_set_no (); - // Set NAN property. - if (is_nan) - m_props.nan_set_yes (); - else - m_props.nan_set_no (); - } - else - { - // Mark when the endpoints can't be +-INF. - if (!is_min) - m_props.ninf_set_no (); - if (!is_max) - m_props.inf_set_no (); - } + // Set NAN property if we're absolutely sure. + if (is_nan && operand_equal_p (min, max)) + m_props.nan_set_yes (); + else if (!HONOR_NANS (m_type)) + m_props.nan_set_no (); + + // Set SIGNBIT property for positive and negative ranges. + if (real_less (&m_max, &dconst0)) + m_props.signbit_set_yes (); + else if (real_less (&dconst0, &m_min)) + m_props.signbit_set_no (); // Check for swapped ranges. gcc_checking_assert (is_nan || tree_compare (LE_EXPR, min, max)); @@ -332,6 +392,16 @@ frange::set (tree min, tree max, value_range_kind kind) verify_range (); } +// Setter for frange from REAL_VALUE_TYPE endpoints. + +void +frange::set (tree type, + const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max, + value_range_kind kind) +{ + set (build_real (type, min), build_real (type, max), kind); +} + // Normalize range to VARYING or UNDEFINED, or vice versa. Return // TRUE if anything changed. // @@ -343,7 +413,15 @@ frange::set (tree min, tree max, value_range_kind kind) bool frange::normalize_kind () { - if (m_kind == VR_RANGE) + // Undefined is viral. + if (m_props.nan_undefined_p () || m_props.signbit_undefined_p ()) + { + set_undefined (); + return true; + } + if (m_kind == VR_RANGE + && real_isinf (&m_min, 1) + && real_isinf (&m_max, 0)) { // No FP properties set means varying. if (m_props.varying_p ()) @@ -351,14 +429,6 @@ frange::normalize_kind () set_varying (m_type); return true; } - // Undefined is viral. - if (m_props.nan_undefined_p () - || m_props.inf_undefined_p () - || m_props.ninf_undefined_p ()) - { - set_undefined (); - return true; - } } else if (m_kind == VR_VARYING) { @@ -366,6 +436,8 @@ frange::normalize_kind () if (!m_props.varying_p ()) { m_kind = VR_RANGE; + m_min = dconstninf; + m_max = dconstinf; return true; } } @@ -385,12 +457,44 @@ frange::union_ (const vrange &v) return true; } - bool ret = m_props.union_ (r.m_props); - ret |= normalize_kind (); + // If one side has a NAN, the union is the other side, plus the union + // of the properties and the possibility of a NAN. + if (get_nan ().yes_p ()) + { + frange_props save = m_props; + *this = r; + m_props = save; + m_props.union_ (r.m_props); + set_nan (fp_prop::VARYING); + if (flag_checking) + verify_range (); + return true; + } + if (r.get_nan ().yes_p ()) + { + m_props.union_ (r.m_props); + set_nan (fp_prop::VARYING); + if (flag_checking) + verify_range (); + return true; + } + + bool changed = m_props.union_ (r.m_props); + if (real_less (&r.m_min, &m_min)) + { + m_min = r.m_min; + changed = true; + } + if (real_less (&m_max, &r.m_max)) + { + m_max = r.m_max; + changed = true; + } + changed |= normalize_kind (); if (flag_checking) verify_range (); - return ret; + return changed; } bool @@ -411,12 +515,46 @@ frange::intersect (const vrange &v) return true; } - bool ret = m_props.intersect (r.m_props); - ret |= normalize_kind (); + // If two NANs are not exactly the same, drop to an unknown NAN, + // otherwise there's nothing to do. + if (get_nan ().yes_p () && r.get_nan ().yes_p ()) + { + if (m_props == r.m_props) + return false; + + *this = frange_nan (m_type); + return true; + } + // ?? Perhaps the intersection of a NAN and anything is a NAN ??. + if (get_nan ().yes_p () || r.get_nan ().yes_p ()) + { + set_varying (m_type); + return true; + } + + bool changed = m_props.intersect (r.m_props); + + if (real_less (&m_min, &r.m_min)) + { + m_min = r.m_min; + changed = true; + } + if (real_less (&r.m_max, &m_max)) + { + m_max = r.m_max; + changed = true; + } + // If the endpoints are swapped, the ranges are disjoint. + if (real_less (&m_max, &m_min)) + { + set_undefined (); + return true; + } + changed |= normalize_kind (); if (flag_checking) verify_range (); - return ret; + return changed; } frange & @@ -424,6 +562,8 @@ frange::operator= (const frange &src) { m_kind = src.m_kind; m_type = src.m_type; + m_min = src.m_min; + m_max = src.m_max; m_props = src.m_props; if (flag_checking) @@ -442,7 +582,83 @@ frange::operator== (const frange &src) const if (varying_p ()) return types_compatible_p (m_type, src.m_type); - return m_props == src.m_props; + if (m_props.get_nan ().yes_p () + || src.m_props.get_nan ().yes_p ()) + return false; + + return (real_identical (&m_min, &src.m_min) + && real_identical (&m_max, &src.m_max) + && m_props == src.m_props + && types_compatible_p (m_type, src.m_type)); + } + return false; +} + +// Return TRUE if range contains the TREE_REAL_CST_PTR in CST. + +bool +frange::contains_p (tree cst) const +{ + if (undefined_p ()) + return false; + + if (varying_p ()) + return true; + + gcc_checking_assert (m_kind == VR_RANGE); + + const REAL_VALUE_TYPE *rv = TREE_REAL_CST_PTR (cst); + if (real_compare (GE_EXPR, rv, &m_min) + && real_compare (LE_EXPR, rv, &m_max)) + { + if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (rv)) + { + if (get_signbit ().yes_p ()) + return real_isneg (rv); + else if (get_signbit ().no_p ()) + return !real_isneg (rv); + else + return true; + } + return true; + } + return false; +} + +// If range is a singleton, place it in RESULT and return TRUE. If +// RESULT is NULL, just return TRUE. +// +// A NAN can never be a singleton. + +bool +frange::singleton_p (tree *result) const +{ + if (m_kind == VR_RANGE && real_identical (&m_min, &m_max)) + { + // Return false for any singleton that may be a NAN. + if (HONOR_NANS (m_type) && !get_nan ().no_p ()) + return false; + + // Return the appropriate zero if known. + if (HONOR_SIGNED_ZEROS (m_type) && zero_p ()) + { + if (get_signbit ().no_p ()) + { + if (result) + *result = build_real (m_type, dconst0); + return true; + } + if (get_signbit ().yes_p ()) + { + if (result) + *result = build_real (m_type, real_value_negate (&dconst0)); + return true; + } + return false; + } + if (result) + *result = build_real (m_type, m_min); + return true; } return false; } @@ -461,13 +677,90 @@ frange::verify_range () gcc_checking_assert (m_props.undefined_p ()); return; } + gcc_checking_assert (!m_props.undefined_p ()); + if (varying_p ()) { gcc_checking_assert (m_props.varying_p ()); return; } + + // We don't support the inverse of an frange (yet). gcc_checking_assert (m_kind == VR_RANGE); - gcc_checking_assert (!m_props.varying_p () && !m_props.undefined_p ()); + + bool is_nan = real_isnan (&m_min) || real_isnan (&m_max); + if (is_nan) + { + // If either is a NAN, both must be a NAN. + gcc_checking_assert (real_identical (&m_min, &m_max)); + gcc_checking_assert (get_nan ().yes_p ()); + } + else + // Make sure we don't have swapped ranges. + gcc_checking_assert (!real_less (&m_max, &m_min)); + + // If we're absolutely sure we have a NAN, the endpoints should + // reflect this, otherwise we'd have more than one way to represent + // a NAN. + if (m_props.get_nan ().yes_p ()) + { + gcc_checking_assert (real_isnan (&m_min)); + gcc_checking_assert (real_isnan (&m_max)); + } + else + { + // Make sure the signbit and range agree. + if (m_props.get_signbit ().yes_p ()) + gcc_checking_assert (real_compare (LE_EXPR, &m_max, &dconst0)); + else if (m_props.get_signbit ().no_p ()) + gcc_checking_assert (real_compare (GE_EXPR, &m_min, &dconst0)); + } + + // If all the properties are clear, we better not span the entire + // domain, because that would make us varying. + if (m_props.varying_p ()) + gcc_checking_assert (!real_isinf (&m_min, 1) || !real_isinf (&m_max, 0)); +} + +// We can't do much with nonzeros yet. +void +frange::set_nonzero (tree type) +{ + set_varying (type); +} + +// We can't do much with nonzeros yet. +bool +frange::nonzero_p () const +{ + return false; +} + +// Set range to [+0.0, +0.0]. + +void +frange::set_zero (tree type) +{ + tree zero = build_zero_cst (type); + set (zero, zero); +} + +// Return TRUE for any [0.0, 0.0] regardless of sign. + +bool +frange::zero_p () const +{ + return (m_kind == VR_RANGE + && real_iszero (&m_min) + && real_iszero (&m_max)); +} + +void +frange::set_nonnegative (tree type) +{ + tree zero = build_zero_cst (type); + tree inf = vrp_val_max (type); + set (zero, inf); } // Here we copy between any two irange's. The ranges can be legacy or @@ -3300,6 +3593,288 @@ range_tests_nonzero_bits () ASSERT_TRUE (r0.varying_p ()); } +// Build an frange from string endpoints. + +static inline frange +frange_float (const char *lb, const char *ub, tree type = float_type_node) +{ + REAL_VALUE_TYPE min, max; + gcc_assert (real_from_string (&min, lb) == 0); + gcc_assert (real_from_string (&max, ub) == 0); + return frange (type, min, max); +} + +static void +range_tests_nan () +{ + frange r0, r1; + REAL_VALUE_TYPE q, r; + + // Equal ranges but with differing NAN bits are not equal. + if (HONOR_NANS (float_type_node)) + { + r1 = frange_float ("10", "12"); + r0 = r1; + ASSERT_EQ (r0, r1); + r0.set_nan (fp_prop::NO); + ASSERT_NE (r0, r1); + r0.set_nan (fp_prop::YES); + ASSERT_NE (r0, r1); + } + + // NAN ranges are not equal to each other. + r0 = frange_nan (float_type_node); + r1 = r0; + ASSERT_FALSE (r0 == r1); + ASSERT_FALSE (r0 == r0); + ASSERT_TRUE (r0 != r0); + + // [5,6] U NAN is [5,6] with an unknown NAN bit. + r0 = frange_float ("5", "6"); + r0.set_nan (fp_prop::NO); + r1 = frange_nan (float_type_node); + r0.union_ (r1); + real_from_string (&q, "5"); + real_from_string (&r, "6"); + ASSERT_TRUE (real_identical (&q, &r0.lower_bound ())); + ASSERT_TRUE (real_identical (&r, &r0.upper_bound ())); + ASSERT_TRUE (r0.get_nan ().varying_p ()); + + // NAN U NAN = NAN + r0 = frange_nan (float_type_node); + r1 = frange_nan (float_type_node); + r0.union_ (r1); + ASSERT_TRUE (real_isnan (&r0.lower_bound ())); + ASSERT_TRUE (real_isnan (&r1.upper_bound ())); + ASSERT_TRUE (r0.get_nan ().yes_p ()); + + // [INF, INF] ^ NAN = VARYING + r0 = frange_nan (float_type_node); + r1 = frange_float ("+Inf", "+Inf"); + r0.intersect (r1); + ASSERT_TRUE (r0.varying_p ()); + + // NAN ^ NAN = NAN + r0 = frange_nan (float_type_node); + r1 = frange_nan (float_type_node); + r0.intersect (r1); + ASSERT_TRUE (r0.get_nan ().yes_p ()); + + // VARYING ^ NAN = NAN. + r0 = frange_nan (float_type_node); + r1.set_varying (float_type_node); + r0.intersect (r1); + ASSERT_TRUE (r0.get_nan ().yes_p ()); + + // Setting the NAN bit to yes, forces to range to [NAN, NAN]. + r0.set_varying (float_type_node); + r0.set_nan (fp_prop::YES); + ASSERT_TRUE (r0.get_nan ().yes_p ()); + ASSERT_TRUE (real_isnan (&r0.lower_bound ())); + ASSERT_TRUE (real_isnan (&r0.upper_bound ())); +} + +static void +range_tests_signed_zeros () +{ + tree zero = build_zero_cst (float_type_node); + tree neg_zero = fold_build1 (NEGATE_EXPR, float_type_node, zero); + REAL_VALUE_TYPE q, r; + frange r0, r1; + + // Since -0.0 == +0.0, a range of [-0.0, -0.0] should contain +0.0 + // and vice versa. + r0 = frange (zero, zero); + r1 = frange (neg_zero, neg_zero); + ASSERT_TRUE (r0.contains_p (zero)); + ASSERT_TRUE (r0.contains_p (neg_zero)); + ASSERT_TRUE (r1.contains_p (zero)); + ASSERT_TRUE (r1.contains_p (neg_zero)); + + // Test contains_p() when we know the sign of the zero. + r0 = frange(zero, zero); + r0.set_signbit (fp_prop::NO); + ASSERT_TRUE (r0.contains_p (zero)); + ASSERT_FALSE (r0.contains_p (neg_zero)); + r0.set_signbit (fp_prop::YES); + ASSERT_TRUE (r0.contains_p (neg_zero)); + ASSERT_FALSE (r0.contains_p (zero)); + + // The intersection of zeros that differ in sign is the empty set. + r0 = frange (zero, zero); + r0.set_signbit (fp_prop::YES); + r1 = frange (zero, zero); + r1.set_signbit (fp_prop::NO); + r0.intersect (r1); + ASSERT_TRUE (r0.undefined_p ()); + + // The union of zeros that differ in sign is a zero with unknown sign. + r0 = frange (zero, zero); + r0.set_signbit (fp_prop::NO); + r1 = frange (zero, zero); + r1.set_signbit (fp_prop::YES); + r0.union_ (r1); + ASSERT_TRUE (r0.zero_p () && r0.get_signbit ().varying_p ()); + + // NAN U [5,6] should be [5,6] with no sign info. + r0 = frange_nan (float_type_node); + r1 = frange_float ("5", "6"); + r0.union_ (r1); + real_from_string (&q, "5"); + real_from_string (&r, "6"); + ASSERT_TRUE (real_identical (&q, &r0.lower_bound ())); + ASSERT_TRUE (real_identical (&r, &r0.upper_bound ())); + ASSERT_TRUE (r0.get_signbit ().varying_p ()); +} + +static void +range_tests_signbit () +{ + frange r0, r1; + + // Setting the signbit drops the range to [-INF, 0]. + r0.set_varying (float_type_node); + r0.set_signbit (fp_prop::YES); + ASSERT_TRUE (real_isinf (&r0.lower_bound (), 1)); + ASSERT_TRUE (real_iszero (&r0.upper_bound ())); + + // Setting the signbit for [-5, 10] crops the range to [-5, 0] with + // the signbit property set. + r0 = frange_float ("-5", "10"); + r0.set_signbit (fp_prop::YES); + ASSERT_TRUE (r0.get_signbit ().yes_p ()); + r1 = frange_float ("-5", "0"); + ASSERT_TRUE (real_identical (&r0.lower_bound (), &r1.lower_bound ())); + ASSERT_TRUE (real_identical (&r0.upper_bound (), &r1.upper_bound ())); + + // Negative numbers should have the SIGNBIT set. + r0 = frange_float ("-5", "-1"); + ASSERT_TRUE (r0.get_signbit ().yes_p ()); + // Positive numbers should have the SIGNBIT clear. + r0 = frange_float ("1", "10"); + ASSERT_TRUE (r0.get_signbit ().no_p ()); + // Numbers containing zero should have an unknown SIGNBIT. + r0 = frange_float ("0", "10"); + ASSERT_TRUE (r0.get_signbit ().varying_p ()); + // Numbers spanning both positive and negative should have an + // unknown SIGNBIT. + r0 = frange_float ("-10", "10"); + ASSERT_TRUE (r0.get_signbit ().varying_p ()); + r0.set_varying (float_type_node); + ASSERT_TRUE (r0.get_signbit ().varying_p ()); + + // Ignore signbit changes when the sign bit is obviously known from + // the range. + r0 = frange_float ("5", "10"); + r0.set_signbit (fp_prop::VARYING); + ASSERT_TRUE (r0.get_signbit ().no_p ()); + r0 = frange_float ("-5", "-1"); + r0.set_signbit (fp_prop::NO); + ASSERT_TRUE (r0.get_signbit ().yes_p ()); +} + +static void +range_tests_floats () +{ + frange r0, r1; + + range_tests_nan (); + range_tests_signbit (); + + if (HONOR_SIGNED_ZEROS (float_type_node)) + range_tests_signed_zeros (); + + // A range of [-INF,+INF] is actually VARYING if no other properties + // are set. + r0 = frange_float ("-Inf", "+Inf"); + if (r0.get_nan ().varying_p ()) + ASSERT_TRUE (r0.varying_p ()); + // ...unless it has some special property... + r0.set_nan (fp_prop::NO); + ASSERT_FALSE (r0.varying_p ()); + + // The endpoints of a VARYING are +-INF. + r0.set_varying (float_type_node); + ASSERT_TRUE (real_identical (&r0.lower_bound (), &dconstninf)); + ASSERT_TRUE (real_identical (&r0.upper_bound (), &dconstinf)); + + // The maximum representable range for a type is still a subset of VARYING. + REAL_VALUE_TYPE q, r; + real_min_representable (&q, float_type_node); + real_max_representable (&r, float_type_node); + r0 = frange (float_type_node, q, r); + // r0 is not a varying, because it does not include -INF/+INF. + ASSERT_FALSE (r0.varying_p ()); + // The upper bound of r0 must be less than +INF. + ASSERT_TRUE (real_less (&r0.upper_bound (), &dconstinf)); + // The lower bound of r0 must be greater than -INF. + ASSERT_TRUE (real_less (&dconstninf, &r0.lower_bound ())); + + // For most architectures, where float and double are different + // sizes, having the same endpoints does not necessarily mean the + // ranges are equal. + if (!types_compatible_p (float_type_node, double_type_node)) + { + r0 = frange_float ("3.0", "3.0", float_type_node); + r1 = frange_float ("3.0", "3.0", double_type_node); + ASSERT_NE (r0, r1); + } + + // [3,5] U [10,12] = [3,12]. + r0 = frange_float ("3", "5"); + r1 = frange_float ("10", "12"); + r0.union_ (r1); + ASSERT_EQ (r0, frange_float ("3", "12")); + + // [5,10] U [4,8] = [4,10] + r0 = frange_float ("5", "10"); + r1 = frange_float ("4", "8"); + r0.union_ (r1); + ASSERT_EQ (r0, frange_float ("4", "10")); + + // [3,5] U [4,10] = [3,10] + r0 = frange_float ("3", "5"); + r1 = frange_float ("4", "10"); + r0.union_ (r1); + ASSERT_EQ (r0, frange_float ("3", "10")); + + // [4,10] U [5,11] = [4,11] + r0 = frange_float ("4", "10"); + r1 = frange_float ("5", "11"); + r0.union_ (r1); + ASSERT_EQ (r0, frange_float ("4", "11")); + + // [3,12] ^ [10,12] = [10,12]. + r0 = frange_float ("3", "12"); + r1 = frange_float ("10", "12"); + r0.intersect (r1); + ASSERT_EQ (r0, frange_float ("10", "12")); + + // [10,12] ^ [11,11] = [11,11] + r0 = frange_float ("10", "12"); + r1 = frange_float ("11", "11"); + r0.intersect (r1); + ASSERT_EQ (r0, frange_float ("11", "11")); + + // [10,20] ^ [5,15] = [10,15] + r0 = frange_float ("10", "20"); + r1 = frange_float ("5", "15"); + r0.intersect (r1); + ASSERT_EQ (r0, frange_float ("10", "15")); + + // [10,20] ^ [15,25] = [15,20] + r0 = frange_float ("10", "20"); + r1 = frange_float ("15", "25"); + r0.intersect (r1); + ASSERT_EQ (r0, frange_float ("15", "20")); + + // [10,20] ^ [21,25] = [] + r0 = frange_float ("10", "20"); + r1 = frange_float ("21", "25"); + r0.intersect (r1); + ASSERT_TRUE (r0.undefined_p ()); +} + void range_tests () { @@ -3308,6 +3883,7 @@ range_tests () range_tests_int_range_max (); range_tests_strict_enum (); range_tests_nonzero_bits (); + range_tests_floats (); range_tests_misc (); } diff --git a/gcc/value-range.h b/gcc/value-range.h index f0075d0..bc00f3d 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -314,29 +314,17 @@ public: bool intersect (const frange_props &other); bool operator== (const frange_props &other) const; FP_PROP_ACCESSOR(nan) - FP_PROP_ACCESSOR(inf) - FP_PROP_ACCESSOR(ninf) + FP_PROP_ACCESSOR(signbit) private: union { struct { unsigned char nan : 2; - unsigned char inf : 2; - unsigned char ninf : 2; + unsigned char signbit : 2; } bits; unsigned char bytes; } u; }; -// Accessors for getting/setting all FP properties at once. - -#define FRANGE_PROP_ACCESSOR(NAME) \ - fp_prop get_##NAME () const { return m_props.get_##NAME (); } \ - void set_##NAME (fp_prop::kind f) \ - { \ - m_props.set_##NAME (f); \ - normalize_kind (); \ - } - // A floating point range. class frange : public vrange @@ -345,34 +333,65 @@ class frange : public vrange public: frange (); frange (const frange &); + frange (tree, tree, value_range_kind = VR_RANGE); + frange (tree type, const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max, + value_range_kind = VR_RANGE); static bool supports_p (const_tree type) { return SCALAR_FLOAT_TYPE_P (type); } virtual tree type () const override; virtual void set (tree, tree, value_range_kind = VR_RANGE) override; + void set (tree type, const REAL_VALUE_TYPE &, const REAL_VALUE_TYPE &, + value_range_kind = VR_RANGE); virtual void set_varying (tree type) override; virtual void set_undefined () override; virtual bool union_ (const vrange &) override; virtual bool intersect (const vrange &) override; + virtual bool contains_p (tree) const override; + virtual bool singleton_p (tree *result = NULL) const override; virtual bool supports_type_p (const_tree type) const override; virtual void accept (const vrange_visitor &v) const override; + virtual bool zero_p () const override; + virtual bool nonzero_p () const override; + virtual void set_nonzero (tree type) override; + virtual void set_zero (tree type) override; + virtual void set_nonnegative (tree type) override; frange& operator= (const frange &); bool operator== (const frange &) const; bool operator!= (const frange &r) const { return !(*this == r); } - - // Each fp_prop can be accessed with get_PROP() and set_PROP(). - FRANGE_PROP_ACCESSOR(nan) - FRANGE_PROP_ACCESSOR(inf) - FRANGE_PROP_ACCESSOR(ninf) + const REAL_VALUE_TYPE &lower_bound () const; + const REAL_VALUE_TYPE &upper_bound () const; + + // Accessors for FP properties. + fp_prop get_nan () const { return m_props.get_nan (); } + void set_nan (fp_prop::kind f); + fp_prop get_signbit () const { return m_props.get_signbit (); } + void set_signbit (fp_prop::kind); private: void verify_range (); bool normalize_kind (); frange_props m_props; tree m_type; + REAL_VALUE_TYPE m_min; + REAL_VALUE_TYPE m_max; }; +inline const REAL_VALUE_TYPE & +frange::lower_bound () const +{ + gcc_checking_assert (!undefined_p ()); + return m_min; +} + +inline const REAL_VALUE_TYPE & +frange::upper_bound () const +{ + gcc_checking_assert (!undefined_p ()); + return m_max; +} + // is_a<> and as_a<> implementation for vrange. // Anything we haven't specialized is a hard fail. @@ -1031,11 +1050,7 @@ vrp_val_max (const_tree type) return wide_int_to_tree (const_cast<tree> (type), max); } if (frange::supports_p (type)) - { - REAL_VALUE_TYPE real; - real_inf (&real); - return build_real (const_cast <tree> (type), real); - } + return build_real (const_cast <tree> (type), dconstinf); return NULL_TREE; } @@ -1049,12 +1064,7 @@ vrp_val_min (const_tree type) if (POINTER_TYPE_P (type)) return build_zero_cst (const_cast<tree> (type)); if (frange::supports_p (type)) - { - REAL_VALUE_TYPE real, real_ninf; - real_inf (&real); - real_ninf = real_value_negate (&real); - return build_real (const_cast <tree> (type), real_ninf); - } + return build_real (const_cast <tree> (type), dconstninf); return NULL_TREE; } @@ -1096,6 +1106,26 @@ frange::frange (const frange &src) *this = src; } +// frange constructor from REAL_VALUE_TYPE endpoints. + +inline +frange::frange (tree type, + const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max, + value_range_kind kind) +{ + m_discriminator = VR_FRANGE; + set (type, min, max, kind); +} + +// frange constructor from trees. + +inline +frange::frange (tree min, tree max, value_range_kind kind) +{ + m_discriminator = VR_FRANGE; + set (min, max, kind); +} + inline tree frange::type () const { @@ -1107,6 +1137,8 @@ frange::set_varying (tree type) { m_kind = VR_VARYING; m_type = type; + m_min = dconstninf; + m_max = dconstinf; m_props.set_varying (); } @@ -1116,6 +1148,40 @@ frange::set_undefined () m_kind = VR_UNDEFINED; m_type = NULL; m_props.set_undefined (); + memset (&m_min, 0, sizeof (m_min)); + memset (&m_max, 0, sizeof (m_max)); +} + +// Set R to maximum representable value for TYPE. + +inline void +real_max_representable (REAL_VALUE_TYPE *r, tree type) +{ + char buf[128]; + get_max_float (REAL_MODE_FORMAT (TYPE_MODE (type)), + buf, sizeof (buf), false); + int res = real_from_string (r, buf); + gcc_checking_assert (!res); +} + +// Set R to minimum representable value for TYPE. + +inline void +real_min_representable (REAL_VALUE_TYPE *r, tree type) +{ + real_max_representable (r, type); + *r = real_value_negate (r); +} + +// Build a NAN of type TYPE. + +inline frange +frange_nan (tree type) +{ + REAL_VALUE_TYPE r; + + gcc_assert (real_nan (&r, "", 1, TYPE_MODE (type))); + return frange (type, r, r); } #endif // GCC_VALUE_RANGE_H diff --git a/gcc/varasm.cc b/gcc/varasm.cc index 4db8506..b0c4d6a 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -62,10 +62,6 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "opts.h" -#ifdef XCOFF_DEBUGGING_INFO -#include "xcoffout.h" /* Needed for external data declarations. */ -#endif - /* The (assembler) name of the first globally-visible object output. */ extern GTY(()) const char *first_global_object_name; extern GTY(()) const char *weak_global_object_name; @@ -1469,6 +1469,9 @@ public: bool is_empty (void) const { return m_vec ? m_vec->is_empty () : true; } + unsigned allocated (void) const + { return m_vec ? m_vec->allocated () : 0; } + unsigned length (void) const { return m_vec ? m_vec->length () : 0; } @@ -2264,6 +2267,18 @@ public: array_slice (const vec<OtherT> &v) : m_base (v.address ()), m_size (v.length ()) {} + template<typename OtherT> + array_slice (vec<OtherT> &v) + : m_base (v.address ()), m_size (v.length ()) {} + + template<typename OtherT> + array_slice (const vec<OtherT, va_gc> *v) + : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} + + template<typename OtherT> + array_slice (vec<OtherT, va_gc> *v) + : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} + iterator begin () { return m_base; } iterator end () { return m_base + m_size; } diff --git a/gcc/xcoffout.cc b/gcc/xcoffout.cc deleted file mode 100644 index bafd355..0000000 --- a/gcc/xcoffout.cc +++ /dev/null @@ -1,494 +0,0 @@ -/* Output xcoff-format symbol table information from GNU compiler. - Copyright (C) 1992-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* Output xcoff-format symbol table data. The main functionality is contained - in dbxout.cc. This file implements the sdbout-like parts of the xcoff - interface. Many functions are very similar to their counterparts in - the former sdbout.c file. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "rtl.h" -#include "tree.h" -#include "diagnostic-core.h" -#include "varasm.h" -#include "output.h" -#include "debug.h" -#include "file-prefix-map.h" /* remap_debug_filename() */ - -#ifdef XCOFF_DEBUGGING_INFO - -/* This defines the C_* storage classes. */ -#include "xcoff.h" -#include "xcoffout.h" -#include "dbxout.h" -#include "gstab.h" - -/* Line number of beginning of current function, minus one. - Negative means not in a function or not using xcoff. */ - -static int xcoff_begin_function_line = -1; -static int xcoff_inlining = 0; - -/* Name of the current include file. */ - -const char *xcoff_current_include_file; - -/* Name of the current function file. This is the file the `.bf' is - emitted from. In case a line is emitted from a different file, - (by including that file of course), then the line number will be - absolute. */ - -static const char *xcoff_current_function_file; - -/* Names of bss and data sections. These should be unique names for each - compilation unit. */ - -char *xcoff_bss_section_name; -char *xcoff_private_data_section_name; -char *xcoff_private_rodata_section_name; -char *xcoff_tls_data_section_name; -char *xcoff_read_only_section_name; - -/* Last source file name mentioned in a NOTE insn. */ - -const char *xcoff_lastfile; - -/* Macro definitions used below. */ - -#define ABS_OR_RELATIVE_LINENO(LINENO) \ -((xcoff_inlining) ? (LINENO) : (LINENO) - xcoff_begin_function_line) - -/* Output source line numbers via ".line". */ -#define ASM_OUTPUT_LINE(FILE,LINENUM) \ - do \ - { \ - /* Make sure we're in a function and prevent output of .line 0, as \ - line # 0 is meant for symbol addresses in xcoff. Additionally, \ - line numbers are 'unsigned short' in 32-bit mode. */ \ - if (xcoff_begin_function_line >= 0) \ - { \ - int lno = ABS_OR_RELATIVE_LINENO (LINENUM); \ - if (lno > 0 && (TARGET_64BIT || lno <= (int)USHRT_MAX)) \ - fprintf (FILE, "\t.line\t%d\n", lno); \ - } \ - } \ - while (0) - -#define ASM_OUTPUT_LFB(FILE,LINENUM) \ -{ \ - if (xcoff_begin_function_line == -1) \ - { \ - xcoff_begin_function_line = (LINENUM) - 1;\ - fprintf (FILE, "\t.bf\t%d\n", (LINENUM)); \ - } \ - xcoff_current_function_file \ - = (xcoff_current_include_file \ - ? xcoff_current_include_file : main_input_filename); \ -} - -#define ASM_OUTPUT_LFE(FILE,LINENUM) \ - do \ - { \ - fprintf (FILE, "\t.ef\t%d\n", (LINENUM)); \ - xcoff_begin_function_line = -1; \ - } \ - while (0) - -#define ASM_OUTPUT_LBB(FILE,LINENUM,BLOCKNUM) \ - fprintf (FILE, "\t.bb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM)) - -#define ASM_OUTPUT_LBE(FILE,LINENUM,BLOCKNUM) \ - fprintf (FILE, "\t.eb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM)) - -static void xcoffout_block (tree, int, tree); -static void xcoffout_source_file (FILE *, const char *, int); - -/* Support routines for XCOFF debugging info. */ - -struct xcoff_type_number -{ - const char *name; - int number; -}; -static const struct xcoff_type_number xcoff_type_numbers[] = { - { "int", -1 }, - { "char", -2 }, - { "short int", -3 }, - { "long int", -4 }, /* fiddled to -31 if 64 bits */ - { "unsigned char", -5 }, - { "signed char", -6 }, - { "short unsigned int", -7 }, - { "unsigned int", -8 }, - /* No such type "unsigned". */ - { "long unsigned int", -10 }, /* fiddled to -32 if 64 bits */ - { "void", -11 }, - { "float", -12 }, - { "double", -13 }, - { "long double", -14 }, - /* Fortran types run from -15 to -29. */ - { "wchar", -30 }, /* XXX Should be "wchar_t" ? */ - { "long long int", -31 }, - { "long long unsigned int", -32 }, - /* Additional Fortran types run from -33 to -37. */ - - /* ??? Should also handle built-in C++ and Obj-C types. There perhaps - aren't any that C doesn't already have. */ -}; - -/* Returns an XCOFF fundamental type number for DECL (assumed to be a - TYPE_DECL), or 0 if dbxout.cc should assign a type number normally. */ -int -xcoff_assign_fundamental_type_number (tree decl) -{ - const char *name; - size_t i; - - /* Do not waste time searching the list for non-intrinsic types. */ - if (DECL_NAME (decl) == 0 || ! DECL_IS_UNDECLARED_BUILTIN (decl)) - return 0; - - name = IDENTIFIER_POINTER (DECL_NAME (decl)); - - /* Linear search, blech, but the list is too small to bother - doing anything else. */ - for (i = 0; i < ARRAY_SIZE (xcoff_type_numbers); i++) - if (!strcmp (xcoff_type_numbers[i].name, name)) - goto found; - return 0; - - found: - /* -4 and -10 should be replaced with -31 and -32, respectively, - when used for a 64-bit type. */ - if (int_size_in_bytes (TREE_TYPE (decl)) == 8) - { - if (xcoff_type_numbers[i].number == -4) - return -31; - if (xcoff_type_numbers[i].number == -10) - return -32; - } - return xcoff_type_numbers[i].number; -} - -/* Print an error message for unrecognized stab codes. */ - -#define UNKNOWN_STAB(STR) \ - internal_error ("no sclass for %s stab (0x%x)", STR, stab) - -/* Conversion routine from BSD stabs to AIX storage classes. */ - -int -stab_to_sclass (int stab) -{ - switch (stab) - { - case N_GSYM: - return C_GSYM; - - case N_FNAME: - UNKNOWN_STAB ("N_FNAME"); - - case N_FUN: - return C_FUN; - - case N_STSYM: - case N_LCSYM: - return C_STSYM; - - case N_MAIN: - UNKNOWN_STAB ("N_MAIN"); - - case N_RSYM: - return C_RSYM; - - case N_SSYM: - UNKNOWN_STAB ("N_SSYM"); - - case N_RPSYM: - return C_RPSYM; - - case N_PSYM: - return C_PSYM; - case N_LSYM: - return C_LSYM; - case N_DECL: - return C_DECL; - case N_ENTRY: - return C_ENTRY; - - case N_SO: - UNKNOWN_STAB ("N_SO"); - - case N_SOL: - UNKNOWN_STAB ("N_SOL"); - - case N_SLINE: - UNKNOWN_STAB ("N_SLINE"); - - case N_DSLINE: - UNKNOWN_STAB ("N_DSLINE"); - - case N_BSLINE: - UNKNOWN_STAB ("N_BSLINE"); - - case N_BINCL: - UNKNOWN_STAB ("N_BINCL"); - - case N_EINCL: - UNKNOWN_STAB ("N_EINCL"); - - case N_EXCL: - UNKNOWN_STAB ("N_EXCL"); - - case N_LBRAC: - UNKNOWN_STAB ("N_LBRAC"); - - case N_RBRAC: - UNKNOWN_STAB ("N_RBRAC"); - - case N_BCOMM: - return C_BCOMM; - case N_ECOMM: - return C_ECOMM; - case N_ECOML: - return C_ECOML; - - case N_LENG: - UNKNOWN_STAB ("N_LENG"); - - case N_PC: - UNKNOWN_STAB ("N_PC"); - - case N_M2C: - UNKNOWN_STAB ("N_M2C"); - - case N_SCOPE: - UNKNOWN_STAB ("N_SCOPE"); - - case N_CATCH: - UNKNOWN_STAB ("N_CATCH"); - - case N_OPT: - UNKNOWN_STAB ("N_OPT"); - - default: - UNKNOWN_STAB ("?"); - } -} - -/* Output debugging info to FILE to switch to sourcefile FILENAME. - INLINE_P is true if this is from an inlined function. */ - -static void -xcoffout_source_file (FILE *file, const char *filename, int inline_p) -{ - if (filename - && (xcoff_lastfile == 0 || strcmp (filename, xcoff_lastfile) - || (inline_p && ! xcoff_inlining) - || (! inline_p && xcoff_inlining))) - { - if (xcoff_current_include_file) - { - fprintf (file, "\t.ei\t"); - output_quoted_string (file, - remap_debug_filename (xcoff_current_include_file)); - fprintf (file, "\n"); - xcoff_current_include_file = NULL; - } - xcoff_inlining = inline_p; - if (strcmp (main_input_filename, filename) || inline_p) - { - fprintf (file, "\t.bi\t"); - output_quoted_string (file, remap_debug_filename (filename)); - fprintf (file, "\n"); - xcoff_current_include_file = filename; - } - xcoff_lastfile = filename; - } -} - -/* Output a line number symbol entry for location (FILENAME, LINE). */ - -void -xcoffout_source_line (unsigned int line, unsigned int column ATTRIBUTE_UNUSED, - const char *filename, int discriminator ATTRIBUTE_UNUSED, - bool is_stmt ATTRIBUTE_UNUSED) -{ - bool inline_p = (strcmp (xcoff_current_function_file, filename) != 0 - || (int) line < xcoff_begin_function_line); - - xcoffout_source_file (asm_out_file, filename, inline_p); - - ASM_OUTPUT_LINE (asm_out_file, line); -} - -/* Output the symbols defined in block number DO_BLOCK. - - This function works by walking the tree structure of blocks, - counting blocks until it finds the desired block. */ - -static unsigned int do_block = 0; - -static void -xcoffout_block (tree block, int depth, tree args) -{ - while (block) - { - /* Ignore blocks never expanded or otherwise marked as real. */ - if (TREE_USED (block)) - { - /* When we reach the specified block, output its symbols. */ - if (BLOCK_NUMBER (block) == do_block) - { - /* Output the syms of the block. */ - if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0) - dbxout_syms (BLOCK_VARS (block)); - if (args) - dbxout_reg_parms (args); - - /* We are now done with the block. Don't go to inner blocks. */ - return; - } - /* If we are past the specified block, stop the scan. */ - else if (BLOCK_NUMBER (block) >= do_block) - return; - - /* Output the subblocks. */ - xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE); - } - block = BLOCK_CHAIN (block); - } -} - -/* Describe the beginning of an internal block within a function. - Also output descriptions of variables defined in this block. - - N is the number of the block, by order of beginning, counting from 1, - and not counting the outermost (function top-level) block. - The blocks match the BLOCKs in DECL_INITIAL (current_function_decl), - if the count starts at 0 for the outermost one. */ - -void -xcoffout_begin_block (unsigned int line, unsigned int n) -{ - tree decl = current_function_decl; - - /* The IBM AIX compiler does not emit a .bb for the function level scope, - so we avoid it here also. */ - if (n != 1) - ASM_OUTPUT_LBB (asm_out_file, line, n); - - do_block = n; - xcoffout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl)); -} - -/* Describe the end line-number of an internal block within a function. */ - -void -xcoffout_end_block (unsigned int line, unsigned int n) -{ - if (n != 1) - ASM_OUTPUT_LBE (asm_out_file, line, n); -} - -/* Called at beginning of function (before prologue). - Declare function as needed for debugging. */ - -void -xcoffout_declare_function (FILE *file, tree decl, const char *name) -{ - size_t len; - - if (*name == '*') - name++; - len = strlen (name); - if (name[len - 1] == ']') - { - char *n = XALLOCAVEC (char, len - 3); - memcpy (n, name, len - 4); - n[len - 4] = '\0'; - name = n; - } - - /* Any pending .bi or .ei must occur before the .function pseudo op. - Otherwise debuggers will think that the function is in the previous - file and/or at the wrong line number. */ - xcoffout_source_file (file, DECL_SOURCE_FILE (decl), 0); - dbxout_symbol (decl, 0); - - /* .function NAME, TOP, MAPPING, TYPE, SIZE - 16 and 044 are placeholders for backwards compatibility */ - fprintf (file, "\t.function .%s,.%s,16,044,FE..%s-.%s\n", - name, name, name, name); -} - -/* Called at beginning of function body (at start of prologue). - Record the function's starting line number, so we can output - relative line numbers for the other lines. - Record the file name that this function is contained in. */ - -void -xcoffout_begin_prologue (unsigned int line, - unsigned int column ATTRIBUTE_UNUSED, - const char *file ATTRIBUTE_UNUSED) -{ - ASM_OUTPUT_LFB (asm_out_file, line); - dbxout_parms (DECL_ARGUMENTS (current_function_decl)); - - /* Emit the symbols for the outermost BLOCK's variables. sdbout.c did this - in sdbout_begin_block, but there is no guarantee that there will be any - inner block 1, so we must do it here. This gives a result similar to - dbxout, so it does make some sense. */ - do_block = BLOCK_NUMBER (DECL_INITIAL (current_function_decl)); - xcoffout_block (DECL_INITIAL (current_function_decl), 0, - DECL_ARGUMENTS (current_function_decl)); - - ASM_OUTPUT_LINE (asm_out_file, line); -} - -/* Called at end of function (before epilogue). - Describe end of outermost block. */ - -void -xcoffout_end_function (unsigned int last_linenum) -{ - ASM_OUTPUT_LFE (asm_out_file, last_linenum); -} - -/* Output xcoff info for the absolute end of a function. - Called after the epilogue is output. */ - -void -xcoffout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED, - const char *file ATTRIBUTE_UNUSED) -{ - /* We need to pass the correct function size to .function, otherwise, - the xas assembler can't figure out the correct size for the function - aux entry. So, we emit a label after the last instruction which can - be used by the .function pseudo op to calculate the function size. */ - - const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); - if (*fname == '*') - ++fname; - fprintf (asm_out_file, "FE.."); - ASM_OUTPUT_LABEL (asm_out_file, fname); -} -#endif /* XCOFF_DEBUGGING_INFO */ diff --git a/gcc/xcoffout.h b/gcc/xcoffout.h deleted file mode 100644 index f28e83e..0000000 --- a/gcc/xcoffout.h +++ /dev/null @@ -1,194 +0,0 @@ -/* XCOFF definitions. These are needed in dbxout.cc, final.cc, - and xcoffout.h. - Copyright (C) 1998-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#ifndef GCC_XCOFFOUT_H -#define GCC_XCOFFOUT_H - -/* Tags and typedefs are C_DECL in XCOFF, not C_LSYM. */ - -#define DBX_TYPE_DECL_STABS_CODE N_DECL - -/* Use the XCOFF predefined type numbers. */ - -#define DBX_ASSIGN_FUNDAMENTAL_TYPE_NUMBER(TYPE) \ - xcoff_assign_fundamental_type_number (TYPE) - -/* Any type with a negative type index has already been output. */ - -#define DBX_TYPE_DEFINED(TYPE) (TYPE_SYMTAB_ADDRESS (TYPE) < 0) - -/* Must use N_STSYM for static const variables (those in the text section) - instead of N_FUN. */ - -#define DBX_STATIC_CONST_VAR_CODE N_STSYM - -/* For static variables, output code to define the start of a static block. */ - -#define DBX_STATIC_BLOCK_START(ASMFILE,CODE) \ -{ \ - if ((CODE) == N_STSYM) \ - fprintf ((ASMFILE), "\t.bs\t%s[RW]\n", xcoff_private_data_section_name);\ - else if ((CODE) == N_LCSYM) \ - fprintf ((ASMFILE), "\t.bs\t%s\n", xcoff_bss_section_name); \ -} - -/* For static variables, output code to define the end of a static block. */ - -#define DBX_STATIC_BLOCK_END(ASMFILE,CODE) \ -{ \ - if ((CODE) == N_STSYM || (CODE) == N_LCSYM) \ - fputs ("\t.es\n", (ASMFILE)); \ -} - -/* We must use N_RPYSM instead of N_RSYM for register parameters. */ - -#define DBX_REGPARM_STABS_CODE N_RPSYM - -/* We must use 'R' instead of 'P' for register parameters. */ - -#define DBX_REGPARM_STABS_LETTER 'R' - -/* Define our own finish symbol function, since xcoff stabs have their - own different format. */ - -#define DBX_FINISH_STABS(SYM, CODE, LINE, ADDR, LABEL, NUMBER) do { \ - if (ADDR) \ - { \ - /* If we are writing a function name, we must emit a dot in \ - order to refer to the function code, not its descriptor. */ \ - if (CODE == N_FUN) \ - putc ('.', asm_out_file); \ - \ - /* If we are writing a function name, we must ensure that \ - there is no storage-class suffix on the name. */ \ - if (CODE == N_FUN && GET_CODE (ADDR) == SYMBOL_REF) \ - { \ - const char *_p = XSTR (ADDR, 0); \ - if (*_p == '*') \ - fputs (_p+1, asm_out_file); \ - else \ - for (; *_p != '[' && *_p; _p++) \ - putc (*_p != '$' ? *_p : '_', asm_out_file); \ - } \ - else \ - output_addr_const (asm_out_file, ADDR); \ - } \ - /* Another special case: N_GSYM always gets the symbol name, \ - whether or not LABEL or NUMBER are set. */ \ - else if (CODE == N_GSYM) \ - assemble_name (asm_out_file, XSTR (XEXP (DECL_RTL (SYM), 0), 0)); \ - else if (LABEL) \ - assemble_name (asm_out_file, LABEL); \ - else \ - dbxout_int (NUMBER); \ - putc (',', asm_out_file); \ - dbxout_int (stab_to_sclass (CODE)); \ - fputs (",0\n", asm_out_file); \ -} while (0) - -/* These are IBM XCOFF extensions we need to reference in dbxout.cc - and xcoffout.cc. */ - -/* AIX XCOFF uses this for typedefs. This can have any value, since it is - only used for translation into a C_DECL storage class. */ -#ifndef N_DECL -#define N_DECL 0x8c -#endif -/* AIX XCOFF uses this for parameters passed in registers. This can have - any value, since it is only used for translation into a C_RPSYM storage - class. */ -#ifndef N_RPSYM -#define N_RPSYM 0x8e -#endif - -/* Name of the current include file. */ - -extern const char *xcoff_current_include_file; - -/* Names of bss and data sections. These should be unique names for each - compilation unit. */ - -extern char *xcoff_bss_section_name; -extern char *xcoff_private_data_section_name; -extern char *xcoff_private_rodata_section_name; -extern char *xcoff_tls_data_section_name; -extern char *xcoff_read_only_section_name; - -/* Last source file name mentioned in a NOTE insn. */ - -extern const char *xcoff_lastfile; - -/* Don't write out path name for main source file. */ -#define NO_DBX_MAIN_SOURCE_DIRECTORY 1 - -/* Write out main source file name using ".file" rather than ".stabs". - We don't actually do this here, because the assembler gets confused if there - is more than one .file directive. rs6000_xcoff_file_start is already - emitting a .file directory, so we don't output one here also. - Initialize xcoff_lastfile. */ -#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(FILE,FILENAME) \ - xcoff_lastfile = (FILENAME) - -/* If we are still in an include file, its end must be marked. */ -#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \ -do { \ - if (xcoff_current_include_file) \ - { \ - fputs ("\t.ei\t", (FILE)); \ - output_quoted_string ((FILE), xcoff_current_include_file); \ - putc ('\n', (FILE)); \ - xcoff_current_include_file = NULL; \ - } \ -} while (0) - -/* Do not emit any marker for XCOFF until assembler allows XFT_CV. */ -#define NO_DBX_GCC_MARKER - -/* XCOFF32 maximum length is 64K; XLC limits to 16K. */ -#define DBX_CONTIN_LENGTH 16384 - -/* XLC uses '?' as continuation character. */ -#define DBX_CONTIN_CHAR '?' - -/* Don't try to use the `x' type-cross-reference character in DBX data. - Also has the consequence of putting each struct, union or enum - into a separate .stabs, containing only cross-refs to the others. */ -#define DBX_NO_XREFS - -/* We must put stabs in the text section. If we don't the assembler - won't handle them correctly; it will sometimes put stabs where gdb - can't find them. */ - -#define DEBUG_SYMS_TEXT - -/* Prototype functions in xcoffout.cc. */ - -extern int stab_to_sclass (int); -extern void xcoffout_begin_prologue (unsigned int, unsigned int, const char *); -extern void xcoffout_begin_block (unsigned, unsigned); -extern void xcoffout_end_epilogue (unsigned int, const char *); -extern void xcoffout_end_function (unsigned int); -extern void xcoffout_end_block (unsigned, unsigned); -extern int xcoff_assign_fundamental_type_number (tree); -extern void xcoffout_declare_function (FILE *, tree, const char *); -extern void xcoffout_source_line (unsigned int, unsigned int, const char *, - int, bool); - -#endif /* GCC_XCOFFOUT_H */ |